Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The definition of hashing and equality for Lists is counter-intuitive and not as useful as it could be #17963

Open
DartBot opened this issue Apr 2, 2014 · 4 comments
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. core-n library-core type-enhancement A request for a change that isn't a bug

Comments

@DartBot
Copy link

DartBot commented Apr 2, 2014

This issue was originally filed by dharcourt@chromium.org


What steps will reproduce the problem?

  1. Run the following program:

  main() {
    var a = [1, 2];
    var b = [1, 2];
    var m = {a: 42};
    print(m[a]);
    print(m[b]);
    print(a == b);
  }

What is the expected output? What do you see instead?

  • Expected: 42, 42, and true.
  • Actual: 42, null, and false.

What version of the product are you using? On what operating system?

Dart VM version: 1.2.0-dev.5.12 (Thu Feb 20 01:54:16 2014) on "macos_x64"

Please provide any additional information below.

  • The fact that Lists implement pointer hashing and pointer comparison reduces their usability. Content hashing and content comparison would provide much better semantics.
  • Obviously the lists in the example above could be made constants to solve the problem in this particular case, but this is not possible in the general case.
  • Similar improvements to equality and hashing could be made for Sets and Maps (see issue List, Set and Map should have a method to compare if elements are equal #2217), but Lists are probably the most important use case.
@lrhn
Copy link
Member

lrhn commented Apr 2, 2014

While I'm sympathetic to the argument for lists, I think it would probably be a breaking change at the current time. It is possible that there are uses of lists as set elements/map keys that rely on the current identity behavior.


Removed Type-Defect label.
Added Type-Enhancement, Library-Core, Area-Library, Triaged labels.

@floitschG
Copy link
Contributor

Given that lists in Dart are mutable there is no good way to compute a hashCode that wouldn't take linear time.
If you need a map that compares lists deeply, pass the appropriate functions to the Map constructor (https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart-collection.LinkedHashMap#id_LinkedHashMap-).
The collection package has functions that compute deep hashcode/equality which can be used for this.

@DartBot
Copy link
Author

DartBot commented Apr 2, 2014

This comment was originally written by dharcourt@chromium.org


#­2: This complexity would be avoided if List's == operator checked the types of the compared lists and returned true only if they were the same. This would makes sense anyways because List subclasses may have additional attributes and characteristics that make them different from other types of list even if they contain the same elements in the same order. With this definition, in the first case presented in comment #­2 (List vs. List<int>) the lists would be equal since the generics wouldn't change the fact that both lists are List instances containing equal elements in the same order, and in the second case (List vs. OtherUsefulList) the lists would be unequal since they're lists of different types. List subclasses wouldn't need to override == unless either: a) They wanted to be comparable for equality to other types of list; or b) They wanted to take into account for equality more than just list type equality, list element equality, and list element order.

#­3: I think the explanation in the previous paragraph should clarify things. Apologies if the original submission was not clear enough. Please ask if questions remain.

#­4: Would it be a problem to have an O(n) hashCode for Lists in Dart? Java has this behavior and I haven't heard of it being a problem. Also, thanks for the pointer to the custom hash functions in map and set constructors, I hadn't considered those.

All of this may be somewhat moot because changing this directly would be a breaking change, as noted in #­1. Is there any way to have the benefits of content based List equality and hashing without backward compatibility issues? It would be nice to avoid custom hash functions for maps and sets and the use of ListEquality, which don't make for beautiful code.

It's interesting to consider that in this respect Strings, which are sequences of characters, don't behave the same as Lists representing the same sequence of characters. Apart from anything else, it seems like it would be an improvement to converge those behaviors towards String's simpler one.

@DartBot
Copy link
Author

DartBot commented Apr 2, 2014

This comment was originally written by dharcourt@chromium.org


#­7: I think you misunderstood my comment: I wasn't claiming that strings were lists of characters. Re-read the comment and feel free to email me if any questions remain.

@DartBot DartBot added Type-Enhancement library-core area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. labels Apr 2, 2014
@kevmoo kevmoo added type-enhancement A request for a change that isn't a bug and removed priority-unassigned labels Feb 29, 2016
@lrhn lrhn added the core-m label Aug 11, 2017
@floitschG floitschG added core-n and removed core-m labels Aug 25, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. core-n library-core type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

4 participants