Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
October 10, 2004 Can classes be used as associative array keys? | ||||
---|---|---|---|---|
| ||||
The documentation says they can, but the following code fails the second assertion: ======================================== class thing { int x; this (int i) { x = i; } } int main () { thing a = new thing (123); thing b = new thing (123); int[thing] map1; map1[a] = 0; map1[b] = 1; int[char[]] map2; map2["123"] = 0; map2["123"] = 1; assert (1 == map2.length); assert (1 == map1.length); return 0; } ======================================== Perhaps I need to write a comparison or hashing member for my class, but the documentation doesn't describe it. Any ideas how I can get this to work? -- |\ _,,,---,,_ ZZZzz /,`.-'`' -. ;-;;,_ |,4- ) )-,_. ,\ ( `'-' '---''(_/--' `-'\_) fL |
October 10, 2004 Re: Can classes be used as associative array keys? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Eric Hanchrow | Eric Hanchrow wrote:
> The documentation says they can, but the following code fails the
> second assertion:
>
> ========================================
> class thing
> {
> int x;
> this (int i) { x = i; }
> }
>
> int main ()
> {
> thing a = new thing (123);
> thing b = new thing (123);
> int[thing] map1;
> map1[a] = 0;
> map1[b] = 1;
>
> int[char[]] map2;
> map2["123"] = 0;
> map2["123"] = 1;
>
> assert (1 == map2.length);
> assert (1 == map1.length);
>
> return 0;
> }
> ========================================
>
> Perhaps I need to write a comparison or hashing member for my class,
> but the documentation doesn't describe it. Any ideas how I can get
> this to work?
>
Classes are standard by reference. So you have two new "things" made, which are not the same. These are added to map1 as a and b. So there are logically two items within the map.
For char[] it is different. You are using it a char as array, which in contrast to a class *does* point to the same item. If you would want to let "thing a" and "thing b" be the same, you should let b point to a, such as:
thing a = new thing(123);
thing b = a;
this would work as you wanted.
Regards,
Sjoerd
|
October 10, 2004 Re: Can classes be used as associative array keys? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Eric Hanchrow | On Sun, 10 Oct 2004 11:45:51 -0700, Eric Hanchrow <offby1@blarg.net> wrote: > The documentation says they can, but the following code fails the > second assertion: > > ======================================== > class thing > { > int x; > this (int i) { x = i; } > } > > int main () > { > thing a = new thing (123); > thing b = new thing (123); > int[thing] map1; > map1[a] = 0; > map1[b] = 1; > > int[char[]] map2; > map2["123"] = 0; > map2["123"] = 1; > > assert (1 == map2.length); > assert (1 == map1.length); > > return 0; > } > ======================================== > > Perhaps I need to write a comparison or hashing member for my class, > but the documentation doesn't describe it. Any ideas how I can get > this to work? Sjoerd is right about the problem with your example above, 'a' and 'b' above do not compare equal because they are references to different blocks of memory. The default comparrison compares memory location. I thought you could define your own opCmp or opEquals operator in order to make the associative array realise that you intend 'a' and 'b' to be 'the same' but all my attempts have failed... class thing { int x; this (int i) { x = i; } int opCmp(thing rhs) { return x-rhs.x; } int opEquals(thing rhs) { return x==rhs.x; } } perhaps someone else can help us both? Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/ |
October 10, 2004 Re: Can classes be used as associative array keys? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | >>>>> "Regan" == Regan Heath writes: Regan> I thought you could define your own opCmp or opEquals Regan> operator in order to make the associative array realise Regan> that you intend 'a' and b' to be 'the same' but all my Regan> attempts have failed... Same here. I'm sure there's a way to do it, or at least, that Walter intends there eventually to be such a way. -- Yahoo uses Javascript in a few places, though not many. I once asked someone there how this worked out, and he said "they ended up learning a lot about different browser versions." --Paul Graham (http://www.paulgraham.com/road.html) |
October 10, 2004 Re: Can classes be used as associative array keys? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Eric Hanchrow | On Sun, 10 Oct 2004 15:47:13 -0700, Eric Hanchrow <offby1@blarg.net> wrote: >>>>>> "Regan" == Regan Heath writes: > > Regan> I thought you could define your own opCmp or opEquals > Regan> operator in order to make the associative array realise > Regan> that you intend 'a' and b' to be 'the same' but all my > Regan> attempts have failed... > > Same here. I'm sure there's a way to do it, or at least, that Walter > intends there eventually to be such a way. I found (after looking in \dmd\src\phobos\internal\object.d) the 'uint toHash()' method, adding one like so: class thing { int x; this (int i) { x = i; } int opCmp(Object p) { thing rhs = cast(thing)p; printf("opCmp %d,%d\n",x,rhs.x); return x-rhs.x; } int opEquals(Object p) { thing rhs = cast(thing)p; printf("opEquals %d,%d\n",x,rhs.x); return x==rhs.x; } uint toHash() { printf("toHash %d\n",x); return x; } } makes it work as desired :) Notice I had to change "opCmp(thing .." to "opCmp(Object .." as well. It would be nice if that was not necessary, after all, the AA does know what type is involved. Perhaps that would require a cast internally so isn't done for efficiency reasons? Perhaps it's done so as you have to handle it being compared to all objects, if that is the case, how do you return not comparable? eg. int opCmp(Object o) { Foo f; Bar b; f = cast(Foo)o; if (f) return compare_with_foo(); b = cast(Bar)o; if (b) return compare_with_bar(); //how do we return 'not comparable?' return 0; } Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/ |
October 10, 2004 Re: Can classes be used as associative array keys? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | On Mon, 11 Oct 2004 12:24:49 +1300, Regan Heath wrote: [snip] > //how do we return 'not comparable?' Throw an exception, maybe? -- Derek Melbourne, Australia 11/10/2004 9:37:18 AM |
October 11, 2004 Re: Can classes be used as associative array keys? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | Regan Heath wrote: <snip> > Perhaps it's done so as you have to handle it being compared to all objects, if that is the case, how do you return not comparable? <snip> You can usually get away with assuming that the RHS is of compatible type. If the cast fails, it will be a null reference and cause an AV. Of course, if you've got mutually comparable classes to be considered separately, that's another matter.... But several of us agree that it's on the stupid side. http://www.digitalmars.com/drn-bin/wwwnews?D/26144 http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/10558 Stewart. |
Copyright © 1999-2021 by the D Language Foundation