Skip to content

Commit

Permalink
Throw an error when coalesce is passed only nothing/missing arguments
Browse files Browse the repository at this point in the history
Remove the one-argument method, which does not allow passing a replacement
value which can never be nothing/missing. The old behavior can still be obtained
by passing Some(nothing)/Some(missing) as last argument.

Also add a tests for recursivevely wrapped values like Some(Some(1)).
  • Loading branch information
nalimilan committed May 19, 2018
1 parent e9df7b6 commit c57971b
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 19 deletions.
45 changes: 34 additions & 11 deletions base/some.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,20 @@ function show(io::IO, x::Some)
end

"""
coalesce(x, y...)
coalesce(x, y, args...)
Return the first value in the arguments which is not equal to
either [`nothing`](@ref) or [`missing`](@ref), or the last argument.
either [`nothing`](@ref) or [`missing`](@ref), or throw an error
if no argument matches this condition.
Unwrap arguments of type [`Some`](@ref).
This function will return `nothing` or `missing` if and only if
the first valid argument which differs from these two values is
`Some(nothing)` or `Some(missing)`. Therefore, the syntax
`coalesce(x, Some(nothing))` or `coalesce(x, Some(missing))` can be used
to indicate that `nothing` or `missing` should be returned when all
arguments are `nothing` or `missing`.
# Examples
```jldoctest
Expand All @@ -51,9 +59,16 @@ julia> coalesce(missing, 1)
julia> coalesce(1, nothing)
1
julia> coalesce(nothing, nothing) # returns nothing, but not printed in the REPL
julia> coalesce(nothing, nothing, 1)
1
julia> coalesce(nothing, nothing)
ERROR: ArgumentError: coalesce requires that least one argument differs from `nothing` or `missing`.
Pass `Some(nothing)` as the last argument to force returning `nothing`.
Stacktrace:
[...]
julia> coalesce(Some(1))
julia> coalesce(Some(1), 0)
1
julia> coalesce(nothing, Some(1))
Expand All @@ -62,13 +77,21 @@ julia> coalesce(nothing, Some(1))
"""
function coalesce end

coalesce(x::Any) = x
coalesce(x::Some) = x.value
coalesce(x::Nothing) = nothing
coalesce(x::Missing) = missing
coalesce(x::Any, y...) = x
coalesce(x::Some, y...) = x.value
coalesce(x::Union{Nothing, Missing}, y...) = coalesce(y...)
coalesce(x::Nothing, y) = y
coalesce(x::Missing, y) = y
coalesce(x::Nothing, y::Some) = y.value
coalesce(x::Missing, y::Some) = y.value
coalesce(x::Nothing, y::Union{Nothing, Missing}) =
throw(ArgumentError(
"""coalesce requires that least one argument differs from `nothing` or `missing`.
Pass `Some(nothing)` as the last argument to force returning `nothing`."""))
coalesce(x::Missing, y::Union{Nothing, Missing}) =
throw(ArgumentError(
"""coalesce requires that least one argument differs from `nothing` or `missing`.
Pass `Some(nothing)` as the last argument to force returning `nothing`."""))
coalesce(x::Any, y, args...) = x
coalesce(x::Some, y, args...) = x.value
coalesce(x::Union{Nothing, Missing}, y, args...) = coalesce(y, args...)

"""
notnothing(x)
Expand Down
24 changes: 16 additions & 8 deletions test/some.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@
# coalesce()

for v in (nothing, missing)
@test coalesce(1) === 1
@test coalesce(v) === v
@test_throws MethodError coalesce(1) === 1
@test_throws MethodError coalesce(v) === v
@test coalesce(v, 1) === 1
@test coalesce(1, v) === 1
@test coalesce(v, v) === v
Expand All @@ -62,8 +62,8 @@ for v in (nothing, missing)
@test coalesce(v, v, 2) === 2
@test coalesce(v, v, v) === v

@test coalesce(Some(1)) === 1
@test coalesce(Some(v)) === v
@test_throws MethodError coalesce(Some(1)) === 1
@test_throws MethodError coalesce(Some(v)) === v
@test coalesce(Some(1), 0) === 1
@test coalesce(Some(v), 0) === v
@test coalesce(v, Some(v)) === v
Expand All @@ -73,10 +73,18 @@ for v in (nothing, missing)
@test coalesce(v, Some(1), Some(2)) === 1
@test coalesce(Some(1), v, Some(2)) === 1

@test coalesce(v, missing) === missing
@test coalesce(v, nothing) === nothing
@test coalesce(v, missing, v) === v
@test coalesce(v, nothing, v) === v
@test_throws ArgumentError coalesce(v, missing) === missing
@test_throws ArgumentError coalesce(v, nothing) === nothing
@test_throws ArgumentError coalesce(v, missing, v) === v
@test_throws ArgumentError coalesce(v, nothing, v) === v

@test coalesce(v, Some(missing)) === missing
@test coalesce(v, Some(nothing)) === nothing
@test coalesce(v, missing, Some(v)) === v
@test coalesce(v, nothing, Some(v)) === v

@test coalesce(Some(Some(1)), 1) === Some(1)
@test coalesce(v, Some(Some(1))) === Some(1)

# issue #26927
a = [missing, nothing, Some(nothing), Some(missing)]
Expand Down

0 comments on commit c57971b

Please sign in to comment.