www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Separate dynamic object arrays for multiple instances of overlying

reply Jonathan <daemon512 gmail.com> writes:
I'm having some trouble creating arrays that are themselves 
unique within multiple instances of an object.  Example code:


```
class individual
{
     int a = 1; // placeholder for data
}

class individualList
{
     individual[] individuals;  // Something likely has to change 
here
}

void main()
{
     individualList list1 = new  individualList();
     assert(list1.individuals.length == 0);
     individual person1 = new individual();
     list1.individuals ~= person1;
     assert(list1.individuals.length == 1);

     individualList list2 = new individualList();
     assert(list2.individuals.length == 0); // breaks, 
list2.individuals.length is 1
}
```


I'd like the array "individuals" to be unique for each instance 
of individualList, but it seems to be using the same list among 
the different instances.  The following code doesn't  work as I 
don't know the required length of the arrays:
```
class individualList
{
     individual[] individuals = new individual[];  // Doesn't 
compile, requires length
}
```
I've looked a  bit and don't see a solution to this within the 
documentation for arrays or objects.

Further information:
This is being used to parse a xml-style file, the example code is 
a base example, I'm having to do this list population a few 
times, one within another.  Some lists have their count displayed 
before starting to add "individuals" so I could use a 
constructor, but some do not (to my  knowledge) have that  
option, and I'd rather use one solution through the whole parser.
Mar 14
next sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
That code example works fine as is.

When you give a value to a field, it places whatever that is into the 
initialize state that is shared between all instances of that type.

As long as its null or allocated in a constructor, it'll work.
Mar 14
prev sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Thursday, 14 March 2024 at 09:43:09 UTC, Jonathan wrote:
 I'm having some trouble creating arrays that are themselves 
 unique within multiple instances of an object.  Example code:


 ```
 class individual
 {
     int a = 1; // placeholder for data
 }

 class individualList
 {
     individual[] individuals;  // Something likely has to 
 change here
 }

 void main()
 {
     individualList list1 = new  individualList();
     assert(list1.individuals.length == 0);
     individual person1 = new individual();
     list1.individuals ~= person1;
     assert(list1.individuals.length == 1);

     individualList list2 = new individualList();
     assert(list2.individuals.length == 0); // breaks, 
 list2.individuals.length is 1
 }
 ```


 I'd like the array "individuals" to be unique for each instance 
 of individualList, but it seems to be using the same list among 
 the different instances.
Shouldn't be. Each non static class member is a distinct thing in each instance of the class. They are not shared across instances. When I paste your code into run.dlang.io and add this: ```D writeln(list1.individuals.length); writeln(list2.individuals.length); ``` No asserts trigger and I see this output as expected: ``` 1 0 ``` Is the code you pasted here exactly what you're running?
Mar 14
parent reply Jonathan <daemon512 gmail.com> writes:
On Thursday, 14 March 2024 at 09:53:27 UTC, Mike Parker wrote:
 On Thursday, 14 March 2024 at 09:43:09 UTC, Jonathan wrote:
 I'm having some trouble creating arrays that are themselves 
 unique within multiple instances of an object.  Example code:


 ```
 class individual
 {
     int a = 1; // placeholder for data
 }

 class individualList
 {
     individual[] individuals;  // Something likely has to 
 change here
 }

 void main()
 {
     individualList list1 = new  individualList();
     assert(list1.individuals.length == 0);
     individual person1 = new individual();
     list1.individuals ~= person1;
     assert(list1.individuals.length == 1);

     individualList list2 = new individualList();
     assert(list2.individuals.length == 0); // breaks, 
 list2.individuals.length is 1
 }
 ```


 I'd like the array "individuals" to be unique for each 
 instance of individualList, but it seems to be using the same 
 list among the different instances.
Shouldn't be. Each non static class member is a distinct thing in each instance of the class. They are not shared across instances. When I paste your code into run.dlang.io and add this: ```D writeln(list1.individuals.length); writeln(list2.individuals.length); ``` No asserts trigger and I see this output as expected: ``` 1 0 ``` Is the code you pasted here exactly what you're running?
You're right, my example code doesn't function as my nonworking code does, sorry about that. No, this is not the same, the code that doesn't work is part of a 1000+ line parser, I thought this example would work the same. I'm trying multiple loops to get the same problem, but I'm having trouble getting it to do so. Will get back when I have a proper example.
Mar 14
parent reply Jonathan <daemon512 gmail.com> writes:
The following seems the be the minimum required for this problem 
to pop up.  I've changed the names to what I'm using in my code 
to make it more clear for me.

```
import std;
class SpectrumList
{
     int count = 2;
     Spectrum[] spectra;
}

class Spectrum
{
     PrecursorList precursorList = new PrecursorList();
}

class PrecursorList
{
  	int count = 3;
     Precursor[] precursors;
}

class Precursor
{
  	string a = "placeholder";
     string b = "loren ipsum";
}

void main()
{
    SpectrumList mySpectrumList = new SpectrumList;
    for(int j=0; j<mySpectrumList.count; ++j)
    {
    	    Spectrum mySpectrum = new Spectrum;
         writeln(mySpectrum.precursorList.precursors.length); // 
should always be 0
         assert(mySpectrum.precursorList.precursors.length == 0);
         for(int k=0; k<mySpectrum.precursorList.count; ++k)
         {
             Precursor myPrecursor = new Precursor;
             mySpectrum.precursorList.precursors ~= myPrecursor;
         }
         mySpectrumList.spectra ~= mySpectrum;
    }
}
```

Output from run.dlang.io:

```
0
3
core.exception.AssertError onlineapp.d(32): Assertion failure
----------------
??:? [0x55676698b006]
??:? [0x55676698ac82]
??:? [0x5567669b11d6]
??:? [0x5567669927ef]
??:? [0x556766989d92]
onlineapp.d:32 [0x556766959f4c]
??:? [0x5567669924bc]
??:? [0x5567669923b6]
??:? [0x55676699220d]
/dlang/ldc-1.35.0/bin/../import/core/internal/entrypoint.d:42 
[0x55676695a1d1]
??:? [0x7efc3bed5d8f]
??:? __libc_start_main [0x7efc3bed5e3f]
??:? [0x556766959c54]
Error: /tmp/onlineapp-ae55ed failed with status: 1
```
Mar 14
next sibling parent reply Basile B. <b2.temp gmx.com> writes:
On Thursday, 14 March 2024 at 10:21:41 UTC, Jonathan wrote:
 The following seems the be the minimum required for this 
 problem to pop up.  I've changed the names to what I'm using in 
 my code to make it more clear for me.

 [...]
Classic. Instead of a static initializer rather uses a constructor for instances. ```d class Spectrum { PrecursorList precursorList; this() { precursorList = new PrecursorList(); } } ```
Mar 14
next sibling parent Jonathan <daemon512 gmail.com> writes:
On Thursday, 14 March 2024 at 12:00:37 UTC, Basile B. wrote:
 On Thursday, 14 March 2024 at 10:21:41 UTC, Jonathan wrote:
 The following seems the be the minimum required for this 
 problem to pop up.  I've changed the names to what I'm using 
 in my code to make it more clear for me.

 [...]
Classic. Instead of a static initializer rather uses a constructor for instances. ```d class Spectrum { PrecursorList precursorList; this() { precursorList = new PrecursorList(); } } ```
This seems to have solved the problem. This thought had crossed my mind at one point, then left before I could implement it. Really appreciate the help!
Mar 14
prev sibling parent reply Matheus <matheus gmail.com> writes:
On Thursday, 14 March 2024 at 12:00:37 UTC, Basile B. wrote:
 On Thursday, 14 March 2024 at 10:21:41 UTC, Jonathan wrote:
 The following seems the be the minimum required for this 
 problem to pop up.  I've changed the names to what I'm using 
 in my code to make it more clear for me.

 [...]
Classic. Instead of a static initializer rather uses a constructor for instances. ```d class Spectrum { PrecursorList precursorList; this() { precursorList = new PrecursorList(); } } ```
I wonder how it would be if we had an error or warning for something like this. For example displaying a message forcing the use of the word "static" and initialize with "static this" when expecting static initialization or construct for new instances. Before someone points out: https://dlang.org/spec/class.html Yes I know, but unfortunately this mistake as Basile noted as "classic", is very common. Matheus.
Mar 14
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 3/14/24 15:44, Matheus wrote:
 On Thursday, 14 March 2024 at 12:00:37 UTC, Basile B. wrote:
 On Thursday, 14 March 2024 at 10:21:41 UTC, Jonathan wrote:
 The following seems the be the minimum required for this problem to 
 pop up.  I've changed the names to what I'm using in my code to make 
 it more clear for me.

 [...]
Classic. Instead of a static initializer rather uses a constructor for instances. ```d class Spectrum {     PrecursorList precursorList;     this()     {         precursorList = new PrecursorList();     } } ```
I wonder how it would be if we had an error or warning for something like this. For example displaying a message forcing the use of the word "static" and initialize with "static this" when expecting static initialization or construct for new instances. Before someone points out: https://dlang.org/spec/class.html Yes I know, but unfortunately this mistake as Basile noted as "classic", is very common. Matheus.
Well, I guess I can still point out that this is what OpenD does: https://github.com/opendlang/opend/pull/8
Mar 16
next sibling parent matheus <matheus gmail.com> writes:
On Saturday, 16 March 2024 at 13:47:42 UTC, Timon Gehr wrote:
 ...
 Well, I guess I can still point out that this is what OpenD 
 does:
 https://github.com/opendlang/opend/pull/8
Indeed and thanks for the info. Matheus.
Mar 16
prev sibling parent Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Saturday, 16 March 2024 at 13:47:42 UTC, Timon Gehr wrote:
 On 3/14/24 15:44, Matheus wrote:
 On Thursday, 14 March 2024 at 12:00:37 UTC, Basile B. wrote:
 On Thursday, 14 March 2024 at 10:21:41 UTC, Jonathan wrote:
 The following seems the be the minimum required for this 
 problem to pop up.  I've changed the names to what I'm using 
 in my code to make it more clear for me.

 [...]
Classic. Instead of a static initializer rather uses a constructor for instances. ```d class Spectrum {     PrecursorList precursorList;     this()     {         precursorList = new PrecursorList();     } } ```
I wonder how it would be if we had an error or warning for something like this. For example displaying a message forcing the use of the word "static" and initialize with "static this" when expecting static initialization or construct for new instances. Before someone points out: https://dlang.org/spec/class.html Yes I know, but unfortunately this mistake as Basile noted as "classic", is very common.
Well, I guess I can still point out that this is what OpenD does: https://github.com/opendlang/opend/pull/8
Too common. https://issues.dlang.org/show_bug.cgi?id=24454
Mar 26
prev sibling parent An Pham <home home.com> writes:
On Thursday, 14 March 2024 at 10:21:41 UTC, Jonathan wrote:
 class Spectrum
 {
     PrecursorList precursorList = new PrecursorList();
 }
 void main()
 {
    SpectrumList mySpectrumList = new SpectrumList;
    for(int j=0; j<mySpectrumList.count; ++j)
    {
    	    Spectrum mySpectrum = new Spectrum;
         writeln(mySpectrum.precursorList.precursors.length); // 
 should always be 0
         assert(mySpectrum.precursorList.precursors.length == 0);
         for(int k=0; k<mySpectrum.precursorList.count; ++k)
         {
             Precursor myPrecursor = new Precursor;
             mySpectrum.precursorList.precursors ~= myPrecursor;
         }
         mySpectrumList.spectra ~= mySpectrum;
    }
 ```
You encounter a gotcha unfriendly construct of D. For every "new Spectrum", there is only one instant of mySpectrum.precursorList hence for subsequence iteration, the list is already filled with myPrecursor hence the assert problem. So either move that static new to constructor or in the loop Cheers Happy coding
Mar 14