www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Can structs be used with associative arrays?

reply Steve Adams <adamss ascinet.com> writes:
 From looking at the description of associative arrays, it looks like I 
should be able to say:

struct A {
   int a;
}

int main()
{
   A[char[]] x;
   x["a"].a = 1;  // causes a runtime error
   return( 0 );
}

But, when compiled and run with 0.128, this generates:
   Error: ArrayBoundsError z.d(8)
Jul 20 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Wed, 20 Jul 2005 18:57:53 -0400, Steve Adams wrote:

  From looking at the description of associative arrays, it looks like I 
 should be able to say:
 
 struct A {
    int a;
 }
 
 int main()
 {
    A[char[]] x;
    x["a"].a = 1;  // causes a runtime error
    return( 0 );
 }
 
 But, when compiled and run with 0.128, this generates:
    Error: ArrayBoundsError z.d(8)

You get this because there is no x["a"] in existence yet. Try this ... struct A { int a; } int main() { A[char[]] x; x["a"] = *(new A); // Create an instance of the struct. x["a"].a = 1; return( 0 ); } -- Derek Melbourne, Australia 21/07/2005 9:11:22 AM
Jul 20 2005
next sibling parent Steve Adams <adamss ascinet.com> writes:
Thanks, that did it.

wrote:

 On Wed, 20 Jul 2005 18:57:53 -0400, Steve Adams wrote:
 
 
 From looking at the description of associative arrays, it looks like I 
should be able to say:

struct A {
   int a;
}

int main()
{
   A[char[]] x;
   x["a"].a = 1;  // causes a runtime error
   return( 0 );
}

But, when compiled and run with 0.128, this generates:
   Error: ArrayBoundsError z.d(8)

You get this because there is no x["a"] in existence yet. Try this ... struct A { int a; } int main() { A[char[]] x; x["a"] = *(new A); // Create an instance of the struct. x["a"].a = 1; return( 0 ); }

Jul 20 2005
prev sibling parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
 int main()
 {
    A[char[]] x;
    x["a"] = *(new A); // Create an instance of the struct.
    x["a"].a = 1;
    return( 0 );
 }

Note the *(new A) will allocate a new A and then copy the contents to x["a"] and then throw away the allocated memory. So a way of doing the same thing without allocating extra memory is to x["a"] = A.init;
Jul 20 2005
next sibling parent Derek Parnell <derek psych.ward> writes:
On Wed, 20 Jul 2005 20:46:26 -0400, Ben Hinkle wrote:

 int main()
 {
    A[char[]] x;
    x["a"] = *(new A); // Create an instance of the struct.
    x["a"].a = 1;
    return( 0 );
 }

Note the *(new A) will allocate a new A and then copy the contents to x["a"] and then throw away the allocated memory. So a way of doing the same thing without allocating extra memory is to x["a"] = A.init;

That's neat. Thanks. -- Derek Melbourne, Australia 21/07/2005 10:49:46 AM
Jul 20 2005
prev sibling next sibling parent Dejan Lekic <leka entropy.tmok.com> writes:
Ben, thanks for this wanderfull hint! :)
-- 
...........
Dejan Lekic
  http://dejan.lekic.org
  
Jul 21 2005
prev sibling next sibling parent reply jicman <jicman_member pathlink.com> writes:
Ben Hinkle says...
 int main()
 {
    A[char[]] x;
    x["a"] = *(new A); // Create an instance of the struct.
    x["a"].a = 1;
    return( 0 );
 }

Note the *(new A) will allocate a new A and then copy the contents to x["a"] and then throw away the allocated memory. So a way of doing the same thing without allocating extra memory is to x["a"] = A.init;

Ben, this is not working for me. However, new is. Take this example: import std.stdio; class ReportTotals { char[] DayDate = ""; int PPHArr[23]; int FPHArr[23]; } void main() { ReportTotals Month[]; Month.length = Month.length + 1; //Month[0] = ReportTotals.init; Month[0] = new ReportTotals(); Month[0].DayDate = "Apr 6"; } if you compile this program, it works. However, if you comment out the "new" line with your suggested .init like, I get an access violation. Why is that? I want to save memory, but I also want it to work. ;-) thanks for the help. josť
Jul 21 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Fri, 22 Jul 2005 04:55:13 +0000 (UTC), jicman wrote:

 Ben Hinkle says...
 int main()
 {
    A[char[]] x;
    x["a"] = *(new A); // Create an instance of the struct.
    x["a"].a = 1;
    return( 0 );
 }

Note the *(new A) will allocate a new A and then copy the contents to x["a"] and then throw away the allocated memory. So a way of doing the same thing without allocating extra memory is to x["a"] = A.init;

Ben, this is not working for me. However, new is. Take this example: import std.stdio; class ReportTotals { char[] DayDate = ""; int PPHArr[23]; int FPHArr[23]; } void main() { ReportTotals Month[]; Month.length = Month.length + 1; //Month[0] = ReportTotals.init; Month[0] = new ReportTotals(); Month[0].DayDate = "Apr 6"; } if you compile this program, it works. However, if you comment out the "new" line with your suggested .init like, I get an access violation. Why is that? I want to save memory, but I also want it to work. ;-) thanks for the help. josť

Because the .init technique was for use with structs and other value-types and not with classes. Structs and Classes do not share the same syntax in D, which makes template writing such a PIA. For structs one would use '*(new Foo)' but for classes one uses 'new Foo'. Yucky, no? -- Derek Melbourne, Australia 22/07/2005 4:34:24 PM
Jul 21 2005
parent jicman <jicman_member pathlink.com> writes:
Derek Parnell says...
On Fri, 22 Jul 2005 04:55:13 +0000 (UTC), jicman wrote:

 Ben Hinkle says...
 int main()
 {
    A[char[]] x;
    x["a"] = *(new A); // Create an instance of the struct.
    x["a"].a = 1;
    return( 0 );
 }

Note the *(new A) will allocate a new A and then copy the contents to x["a"] and then throw away the allocated memory. So a way of doing the same thing without allocating extra memory is to x["a"] = A.init;

Ben, this is not working for me. However, new is. Take this example: import std.stdio; class ReportTotals { char[] DayDate = ""; int PPHArr[23]; int FPHArr[23]; } void main() { ReportTotals Month[]; Month.length = Month.length + 1; //Month[0] = ReportTotals.init; Month[0] = new ReportTotals(); Month[0].DayDate = "Apr 6"; } if you compile this program, it works. However, if you comment out the "new" line with your suggested .init like, I get an access violation. Why is that? I want to save memory, but I also want it to work. ;-) thanks for the help. josť

Because the .init technique was for use with structs and other value-types and not with classes.

Aaaaah... It would seem to me that classes should also use it.
Structs and Classes do not share the same syntax in D, which makes template
writing such a PIA. 

right away with "new Blah();".
For structs one would use '*(new Foo)' but for classes one uses 'new Foo'.
Yucky, no?

Indeed. I would have set them the same. But I still love D. I guess no language can be perfect. :-) thanks for the explanation. josť
Jul 22 2005
prev sibling parent reply Tim Locke <root vic-20.net> writes:
On Wed, 20 Jul 2005 20:46:26 -0400, "Ben Hinkle"
<ben.hinkle gmail.com> wrote:

 int main()
 {
    A[char[]] x;
    x["a"] = *(new A); // Create an instance of the struct.
    x["a"].a = 1;
    return( 0 );
 }

Note the *(new A) will allocate a new A and then copy the contents to x["a"] and then throw away the allocated memory. So a way of doing the same thing without allocating extra memory is to x["a"] = A.init;

What is the concise method of initializing the members of my array of structs? It seems long-handed to do this: x["a"].a = 1; x["a"].b = 2; etc. Can this be shortened? According to spec_DMD_0.109.pdf, pages 100-101, I *think* I should be able to do something like this: x["a"] = {a:1, b:2}; But the compiler gives me the following error: "expression expected, not '{'". I also tried replacing {} with () and got "found ':' when expecting ')'". Thank you. -- On the Internet, no one knows you're [using] a VIC-20.
Apr 29 2006
parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Tim Locke wrote:
 On Wed, 20 Jul 2005 20:46:26 -0400, "Ben Hinkle"
 <ben.hinkle gmail.com> wrote:
 
 
int main()
{
   A[char[]] x;
   x["a"] = *(new A); // Create an instance of the struct.
   x["a"].a = 1;
   return( 0 );
}

Note the *(new A) will allocate a new A and then copy the contents to x["a"] and then throw away the allocated memory. So a way of doing the same thing without allocating extra memory is to x["a"] = A.init;

What is the concise method of initializing the members of my array of structs? It seems long-handed to do this: x["a"].a = 1; x["a"].b = 2; etc. Can this be shortened? According to spec_DMD_0.109.pdf, pages 100-101, I *think* I should be able to do something like this: x["a"] = {a:1, b:2}; But the compiler gives me the following error: "expression expected, not '{'". I also tried replacing {} with () and got "found ':' when expecting ')'". Thank you. -- On the Internet, no one knows you're [using] a VIC-20.

The {a:1, b:2} format is the struct static initializer syntax, used with static and const declerations only, sadly. Hopefully in the future it becomes more general purpose (related issues to array literals). While it isn't perfect, you can do this, which at least reduces the number of array lookups to one: # with (x["a"]) { a = 1; b= 2; } In fact, I guess you could technically even do: # with (x["a"]) a = 1, b = 2; # with (x["b"] = A.init) a = 1, b = 2; So long as with() doesn't require braces after it. (I think it does, mostly because nobody ever thought of a case where you wouldn't need them... suppose I just did.) -- Chris Nicholson-Sauls
Apr 30 2006
parent Tim Locke <root vic-20.net> writes:
On Sun, 30 Apr 2006 02:41:43 -0500, Chris Nicholson-Sauls
<ibisbasenji gmail.com> wrote:

Tim Locke wrote:
 What is the concise method of initializing the members of my array of
 structs? It seems long-handed to do this:
 
 x["a"].a = 1;
 x["a"].b = 2;
 etc.
 
 Can this be shortened? According to spec_DMD_0.109.pdf, pages 100-101,
 I *think* I should be able to do something like this:
 
 x["a"] = {a:1, b:2};
 
 But the compiler gives me the following error: "expression expected,
 not '{'". I also tried replacing {} with () and got "found ':' when
 expecting ')'".

The {a:1, b:2} format is the struct static initializer syntax, used with static and const declerations only, sadly. Hopefully in the future it becomes more general purpose (related issues to array literals). While it isn't perfect, you can do this, which at least reduces the number of array lookups to one: # with (x["a"]) { a = 1; b= 2; } In fact, I guess you could technically even do: # with (x["a"]) a = 1, b = 2; # with (x["b"] = A.init) a = 1, b = 2; So long as with() doesn't require braces after it. (I think it does, mostly because nobody ever thought of a case where you wouldn't need them... suppose I just did.)

Thanks for the help. I didn't expect so many options. -- On the Internet, no one knows you're [using] a VIC-20.
Apr 30 2006