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

Adding comparison/hashing to Base.Some #35911

Open
schlichtanders opened this issue May 16, 2020 · 7 comments
Open

Adding comparison/hashing to Base.Some #35911

schlichtanders opened this issue May 16, 2020 · 7 comments
Labels
equality Issues relating to equality relations: ==, ===, isequal feature Indicates new feature / enhancement requests hashing

Comments

@schlichtanders
Copy link

schlichtanders commented May 16, 2020

Dear Julia community,

what started as a short discourse discussion I would like to rephrase as a change request.

Currently, Base.Some is treated like Ref in that Some([]) != Some([]), unlike Vector for instance. However in other programming languages, Some actually behaves more like Vector in the sense that it is paired with Nothing and in this combination represents a Container of either one or zero elements.

For instance in Scala Some(List()) == Some(List()).

For consistency with the general semantics of Some/Option/Optional/Maybe (or however it might be called in other programming languages), I would plead for adding the following two lines to Base

Base.:(==)(a::Some, b::Some) = a.value == b.value
Base.hash(a::Some) = hash(a.value)

This is a breaking change.

@tpapp
Copy link
Contributor

tpapp commented May 16, 2020

It would be great to understand your use case for this.

The motivation for Union{Nothing,Some{T}} (compared to Union{Nothing,T}) was being able to distinguish functions returning nothing as the actual result (T === Nothing). This usually means that the payload is unpacked at some point — as I suggested in the discussion, it is somewhat unusual for Some wrappers to have an extended lifetime and be used as containers. Instead of doing

y = f(x)     # obtain a value
y == Some(b) # compare

in a lot of contexts it might be more idiomatic to do

something(f(x)) == b

Doing this also allows all operations that would be valid for the payload (eg <, etc).

@schlichtanders
Copy link
Author

The use cases which brought me here is that I ported an ExtensibleEffects framework to Julia. Within ExtensibleEffects I am working on container level, defining how containers translate to for loops, roughly speaking. In addition to for-loops, which only execute things, ExtensibleEffect construct appropriate return types.

Nothing is a valid container in this regard, the empty container. Similarly Some is a valid container. However if I would use Union{Nothing,T}, I would have to decide whether T is a valid container (might be Vector for instance), or a plain value.
To solve this ambiguity the natural way is to enforce that only container types are possible for T, hence plain values need to be given as Some{T} instead of plain T.

The use of the Some here is not internal, but on the interface side of ExtensibleEffects.

ExtensibleEffects are of course only one example, anything which works on Container-Level semantics and needs to distinguish Container from Value would may use Some for interfacing.

@andyferris
Copy link
Member

andyferris commented May 20, 2020

I would plead for adding the following two lines to Base.

You also need

Base.isequal(a::Some, b::Some) = isequal(a.value, b.value)
Base.isless(a::Some, b::Some) = isless(a.value, b.value)

and the hash implementation needs to take a second UInt input (and ideally be seeded by some randomly selected numbers to represent the type).

@andyferris
Copy link
Member

I would plead

Also - I find the most effective way of getting something small like this is to submit a PR, if you are up for it? :)

@tkf
Copy link
Member

tkf commented May 20, 2020

FYI, there is a PR for turning Some to a singleton container so that it can be used for broadcasting instead of Ref #35778.

@andyferris
Copy link
Member

Nice! Though that PR still doesn’t add these comparisons/hash definition, which seem reasonable with or without considering it a “container”.

@schlichtanders schlichtanders changed the title Treat Base.Some as a Container Adding comparison/hashing to Base.Some Jun 3, 2020
@schlichtanders
Copy link
Author

I never setup Julia in development for creating pullrequest, but indeed this seems like a great occasion to go for it.

@andyferris thanks for mentioning isequal and isless
@tkf thanks for the pointer to #35778. I read through it and also think, that the PR is separate in scope. I changed the title here respectively to avoid confusion.

okay, so it is time for me to create my first pull request :)

@nsajko nsajko added feature Indicates new feature / enhancement requests hashing equality Issues relating to equality relations: ==, ===, isequal labels Dec 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
equality Issues relating to equality relations: ==, ===, isequal feature Indicates new feature / enhancement requests hashing
Projects
None yet
Development

No branches or pull requests

5 participants