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

issetequal and issubset being weird with custom == on structs #41748

Closed
lgoettgens opened this issue Jul 31, 2021 · 2 comments
Closed

issetequal and issubset being weird with custom == on structs #41748

lgoettgens opened this issue Jul 31, 2021 · 2 comments

Comments

@lgoettgens
Copy link
Contributor

When creating a struct with some non-primitive field, e.g. of type Vector{Int64}, and overwriting the == function of the struct to just do == on their fields, the issetequal function on vectors on that struct behaves in an undesired way. As one can see in the last three lines of the code example, the issetequal is in this case not equivalent to issubset in both directions, contrary to the claim in the documentation:

Equivalent to a ⊆ b && b ⊆ a but more efficient when possible.
Base.issetequal docs

julia> versioninfo()
Julia Version 1.6.2
Commit 1b93d53fc4 (2021-07-14 15:36 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.1 (ORCJIT, skylake)

julia> struct S
           x :: Vector{Int64}
       end

julia> Base.:(==)(s1::S, s2::S) = s1.x == s2.x

julia> a = S([])
S(Int64[])

julia> b = S([])
S(Int64[])

julia> a == b
true

julia> issetequal([a],[a])
true

julia> issetequal([a],[b])
false

julia> issubset([a],[b])
true

julia> issubset([b],[a])
true
@lgoettgens
Copy link
Contributor Author

I've experienced similar results for issubset for sets. With the definitions as above

julia> a == a
true

julia> issubset([a], Set([a]))
true

julia> a == b
true

julia> issubset([a], Set([b]))
false

Due to #26198, this should stretch to issubset for vectors of length > 70 as well.

@lgoettgens lgoettgens changed the title issetequal being weird with custom == on structs issetequal and issubset being weird with custom == on structs Jul 31, 2021
@rfourquet
Copy link
Member

It's probably because you implemented == but not hash. To use your objects as keys in dictionaries or elements in sets, if you define == (or isequal) for them, you must also define hash.
It's mentioned in the docstring for ==:

isequal falls back to ==, so new methods of == will be used by the Dict type to compare keys. If your type will be used as a dictionary key, it should therefore also implement hash.

And in the docstring of hash:

hash(x): Compute an integer hash code such that isequal(x,y) implies hash(x)==hash(y)

Here you have:

julia> isequal(a, b)
true

julia> hash(a) == hash(b)
false

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants