www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Associative arrays, opCmp, opEquals and toHash in 2.066.0-b4

reply Jacob Carlborg <doob me.com> writes:
What's up with associative arrays, opCmp, opEquals and toHash in 
2.066.0-b4. I'm trying to compile Tango with the latest beta and I'm 
getting this error:

"Error: AA key type TagIndex now requires equality rather than comparison"

Four months ago "opCmp" was added to "TagIndex" to fix some compile 
error in 2.065.0 and now it complains on "opCmp" being defined.

If I add "opEquals" it complains that I need to define toHash.

What exactly do I need to define to have a struct with two ints working 
as a key in an associative array?

-- 
/Jacob Carlborg
Jul 21 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Jacob Carlborg:

 "Error: AA key type TagIndex now requires equality rather than 
 comparison"
Hashing protocol has being finally fixed.
 What exactly do I need to define to have a struct with two ints 
 working as a key in an associative array?
opEquals and opHash. But if your struct has only two ints as fields, it should work even if you don't define both methods. Bye, bearophile
Jul 21 2014
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
On 7/21/14, 9:49 AM, bearophile wrote:
 But if your struct has only two ints as fields, it
 should work even if you don't define both methods.
Wat?
Jul 21 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Ary Borenszweig:

 Wat?
Hash methods should be automatic for simple structs. Bye, bearophile
Jul 21 2014
parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 21.07.2014 16:34, schrieb bearophile:
 Ary Borenszweig:

 Wat?
Hash methods should be automatic for simple structs. Bye, bearophile
That would be too much magic => special cases one has to know about. Cheers, Daniel
Jul 21 2014
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Daniel Gibson:

 That would be too much magic => special cases one has to know 
 about.
What special cases? It works for POD structs. If you want a different hashing behavior (example: you want to ignore some fields), you define the two methods. struct Foo { double x; int y; string s; } void main() { import std.stdio; bool[Foo] aa; aa[Foo(1.0, 2, "hello".idup)] = true; aa[Foo(1.0, 1, "hello".idup)] = false; aa[Foo(1.0, 2, "hello".idup)] = false; aa.writeln; } Outputs: [Foo(1, 1, "hello"):false, Foo(1, 2, "hello"):false] This was a very old large bug of D. Now it's fixed. Rejoice. Bye, bearophile
Jul 21 2014
prev sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
On 7/21/14, 11:39 AM, Daniel Gibson wrote:
 Am 21.07.2014 16:34, schrieb bearophile:
 Ary Borenszweig:

 Wat?
Hash methods should be automatic for simple structs. Bye, bearophile
That would be too much magic => special cases one has to know about. Cheers, Daniel
Ah, good. I though it only worked for structs with two ints :-P
Jul 21 2014
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2014-07-21 14:49, bearophile wrote:

 opEquals and opHash. But if your struct has only two ints as fields, it
 should work even if you don't define both methods.
If the struct already has opCmp I need to defined opEquals and toHash? -- /Jacob Carlborg
Jul 21 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Jacob Carlborg:

 If the struct already has opCmp I need to defined opEquals and 
 toHash?
From what I know, the new hash protocol requires toHash and opEquals. I think that now opCmp is not used by hashing. I don't know if you define just toHash and opCmp it uses opCmp as fallback. Bye, bearophile
Jul 21 2014
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Mon, Jul 21, 2014 at 04:42:34PM +0000, bearophile via Digitalmars-d wrote:
 Jacob Carlborg:
 
If the struct already has opCmp I need to defined opEquals and toHash?
From what I know, the new hash protocol requires toHash and opEquals. I think that now opCmp is not used by hashing.
Yes, finally that has been fixed.
 I don't know if you define just toHash and opCmp it uses opCmp as
 fallback.
[...] I'm inclined to say, file a regression bug. If opCmp is defined but opEquals isn't, the compiler should auto-generate opEquals (as opCmp(...)==0). Requiring the user to implement a separate opEquals when opCmp is already there is nonsensical, and opens the door to stupid bugs due to increased boilerplate. (Of course, if the user also defines opEquals manually, that's fine. But if he doesn't, the compiler should do the Right Thing(tm).) In any case, if either opCmp or opEquals (or both) is defined, then toHash must be defined, since obviously the user doesn't want the default POD comparison implementation, and toHash must always be consistent with opCmp/opEquals otherwise the AA will break. T -- "640K ought to be enough" -- Bill G., 1984. "The Internet is not a primary goal for PC usage" -- Bill G., 1995. "Linux has no impact on Microsoft's strategy" -- Bill G., 1999.
Jul 21 2014
next sibling parent reply "w0rp" <devw0rp gmail.com> writes:
A rule I learned from writing Java is that if you implement 
equality, you must also implement hashing, and if you implelement 
hashing you must implement equality. I believe this is actually a 
general truth of programming in any language, and now D has the 
right kind of semantics.

On an off topic note, I noticed your signature, H.S. Teoh.

 "640K ought to be enough" -- Bill G., 1984.
That quote is well known for being fabricated. The year varies wildly. There's no evidence of Bill ever saying it which isn't someone saying, "Trust me, I heard him say it once."
Jul 21 2014
parent "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Mon, Jul 21, 2014 at 06:28:48PM +0000, w0rp via Digitalmars-d wrote:
 A rule I learned from writing Java is that if you implement equality,
 you must also implement hashing, and if you implelement hashing you
 must implement equality. I believe this is actually a general truth of
 programming in any language, and now D has the right kind of
 semantics.
This should generally be obvious, since the AA has to hash the object, then distinguish between objects with the same hash by comparing them with some kind of comparison operator. Obviously, if the hash function is inconsistent with this comparison operator, then you're going to get inconsistent behaviour out of the AA. Now, one *could* argue that in some cases, you could implement custom equality but use the default hash function, because you know that your custom equality is consistent with it, but I'd say this is a risky assumption because if it turns out that it's actually *not* consistent, then you end up with a very hard-to-trace bug. So in general, requiring that either you use default equality and hash, or redefine both, seems to be the most logical approach.
 On an off topic note, I noticed your signature, H.S. Teoh.
 
"640K ought to be enough" -- Bill G., 1984.
That quote is well known for being fabricated. The year varies wildly. There's no evidence of Bill ever saying it which isn't someone saying, "Trust me, I heard him say it once."
Funny, your reply prompted me to search for the attribution, and I came across this: http://imranontech.com/2007/02/20/did-bill-gates-say-the-640k-line/ Of course, most of my quotes are meant to be humorous in some way, so they shouldn't be taken 100% seriously. So I just changed it to: "640K ought to be enough" -- Bill G. (allegedly), 1984. "The Internet is not a primary goal for PC usage" -- Bill G., 1995. "Linux has no impact on Microsoft's strategy" -- Bill G., 1999. ;-) T -- Computers are like a jungle: they have monitor lizards, rams, mice, c-moss, binary trees... and bugs.
Jul 21 2014
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2014-07-21 20:17, H. S. Teoh via Digitalmars-d wrote:

 I'm inclined to say, file a regression bug. If opCmp is defined but
 opEquals isn't, the compiler should auto-generate opEquals (as
 opCmp(...)==0).  Requiring the user to implement a separate opEquals
 when opCmp is already there is nonsensical, and opens the door to stupid
 bugs due to increased boilerplate. (Of course, if the user also defines
 opEquals manually, that's fine. But if he doesn't, the compiler should
 do the Right Thing(tm).)
Filed as https://issues.dlang.org/show_bug.cgi?id=13179 -- /Jacob Carlborg
Jul 21 2014