digitalmars.D - Can classes be used as associative array keys?
- Eric Hanchrow (31/31) Oct 10 2004 The documentation says they can, but the following code fails the
- Sjoerd van Leent (13/46) Oct 10 2004 Classes are standard by reference. So you have two new "things" made,
- Regan Heath (24/50) Oct 10 2004 Sjoerd is right about the problem with your example above, 'a' and 'b'
- Eric Hanchrow (12/13) Oct 10 2004 Regan> I thought you could define your own opCmp or opEquals
- Regan Heath (48/55) Oct 10 2004 I found (after looking in \dmd\src\phobos\internal\object.d) the 'uint
- Derek Parnell (7/8) Oct 10 2004 Throw an exception, maybe?
-
Stewart Gordon
(11/13)
Oct 11 2004
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
Oct 10 2004
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
Oct 10 2004
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/
Oct 10 2004
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)"Regan" == Regan Heath writes:
Oct 10 2004
On Sun, 10 Oct 2004 15:47:13 -0700, Eric Hanchrow <offby1 blarg.net> wrote: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/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."Regan" == Regan Heath writes:
Oct 10 2004
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
Oct 10 2004
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.
Oct 11 2004