Julia: Adding comparison/hashing to Base.Some

Created on 16 May 2020  Â·  7Comments  Â·  Source: JuliaLang/julia

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.

Most helpful comment

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 :)

All 7 comments

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).

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.

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).

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? :)

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

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

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 :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tkoolen picture tkoolen  Â·  3Comments

wilburtownsend picture wilburtownsend  Â·  3Comments

arshpreetsingh picture arshpreetsingh  Â·  3Comments

felixrehren picture felixrehren  Â·  3Comments

manor picture manor  Â·  3Comments