Maybe.jl
Tutorial is the best place to start.
Maybe
Maybe — ModuleMaybe.jl: Optional value handling for Julia
Maybe.jl provides functions and macros for handling the values of type Union{Some,Nothing}; i.e., option type. The main entry point for the optional value handling is the macro @?:
julia> using Maybe
julia> data = [1, 3, 2, 1];
julia> @? data[findfirst(iseven, data)]
Some(2)
julia> y = @? data[findfirst(>=(4), data)]
julia> @assert y === nothingMaybe.jl also provides low-level functions such as Maybe.get which is the "Maybe" variant of Base.get:
julia> Maybe.get(Dict(:a => 1), :a)
Some(1)
julia> @assert Maybe.get(Dict(:a => 1), :b) === nothingSee more in the documentation.
Maybe.T — ConstantMaybe.T{T}A shorthand for Union{Some{T},Nothing}.
Maybe.@? — Macro@? expr
@? :debug expr"Lift" functions to operate on Union{Some{T}, Nothing}.
Idea:
- Each function
f(::T₁, ..., ::Tₙ) -> ::Ris (conceptually) lifted tof′(::Union{Some{T₁}, Nothing}, ..., ::Union{Some{Tₙ}, Nothing}) -> ::Union{Some{R}, R, Nothing}. - If any of the returned value is
nothing, the evaluation ofexprin@?short-circuits and evaluates tonothing.
Debugging support (experimental): In the two-argument form @? :debug expr (:debug is the literal symbol :debug), @? inserts @debug logging statements for all possible short-circuiting points. This logging statement prints the expression that is evaluated to nothing and all the local variables using Base.@locals. This macro also inserts a call to a no-op function Maybe._break. When using Debugger.jl, the state just before exit can be examined by adding it to the breakpoint with bp add Maybe._break.
See the tutorial for more information.
Examples
julia> using Maybe
julia> dict = Dict(:a => Dict(:b => 1));
julia> @? dict[:a][:b] + 2
Some(3)
julia> @? dict[:a][:b] + dict[:c] # => nothingThe expression in @? short-circuits when a call returns nothing:
julia> f() = nothing;
julia> @? println(f())Some is unwrapped when it appears in the argument position:
julia> f() = Some("hello");
julia> @? println(f())
helloNon-nothing returned value is always ensured to be wrapped in Some at the end
julia> f() = "hello";
julia> @? f()
Some("hello")
julia> g() = Some("hello");
julia> @? g()
Some("hello")nothing literal is always wrapped
julia> @? Some(nothing)
Some(nothing)return $expr does not return when $expr evaluates to nothing
julia> f() = (@? return identity(nothing); return 1);
julia> f()
1return $expr returns Some($expr):
julia> @? 1 + 1
Some(2)
julia> f() = @? return 1 + 1;
julia> f()
Some(2)$(...) can be used for switching to the normal evaluation
julia> @? Some(Some(Some(1)))
Some(1)
julia> @? $(Some(Some(Some(1))))
Some(Some(Some(Some(1))))$f(...) can be used for extra wrapping with Some
julia> f() = Some("hello");
julia> @? f()
Some("hello")
julia> @? $f()
Some(Some("hello"))@? recursively transforms functions
julia> @? f(dict, i, j, k) =
get(dict, i) do
dict[j] + dict[k]
end;
julia> f(Dict(), :a, :b, :c)
julia> f(Dict(:a => 1), :a, :b, :c)
Some(1)
julia> f(Dict(:b => 1), :a, :b, :c)
julia> f(Dict(:b => 1, :c => 2), :a, :b, :c)
Some(3)Maybe.@something — Macro@something(ex₁, ex₂, ..., exₙ)
@something{ex₁; ex₂; ...; exₙ}
@something {ex₁; ex₂; ...; exₙ}A lazy version of something(x₁, x₂, ..., xₙ). Evaluate exᵢ one by one and return something(result) of the first non-nothing result of exᵢ. Throw an error if everything is evaluated to nothing.
@something{ex₁; ex₂; ...; exₙ} requires Juila >= 1.5.
Examples
julia> using Maybe: @something
julia> @something(
(println("first"); nothing),
(println("second"); 2),
(println("third"); 3),
)
first
second
2
julia> function maybe_add(xs)
a = @something(get(xs, 1, nothing), return)
b = @something(get(xs, 2, nothing), return)
return a + b
end;
julia> maybe_add([])
julia> maybe_add([3, 4])
7
julia> @something(nothing, nothing, nothing)
ERROR: ArgumentError: all evaluated as `nothing`
[...]Since @something is often used with @?, the form @something {ex₁; ex₂; ...; exₙ} can also be used to avoid extra parentheses:
julia> using Maybe: @something, @?
julia> d = Dict(:a => Dict(:b => 1, :c => nothing));
julia> @something {
@? d[:A][:B];
@? d[:A][:b];
@? d[:a][:b];
@? d[:c][:d];
}
1
julia> @something(
(@? d[:A][:B]),
(@? d[:A][:b]),
(@? d[:a][:b]),
(@? d[:c][:d]),
)
1Maybe.eltype — FunctionMaybe.eltype(itr) -> Some(T::Type) or nothingReturn the element type of iterator if known.
Examples
julia> using Maybe
julia> Maybe.eltype(x + 0 for x in 1:3)
julia> Maybe.eltype(1:0.1:3)
Some(Float64)Maybe.err — FunctionMaybe.err(Err(x)) -> Some(x)
Maybe.err(Ok(_)) -> nothingReturn a Some by re-wrapping a value inside an Err result; return nothing on an Ok result.
See also Maybe.ok.
Examples
julia> using Maybe, Try
julia> Maybe.err(Ok(1)) === nothing
true
julia> Maybe.err(Err(1))
Some(1)Maybe.first — FunctionMaybe.first(xs) -> Some(x) or nothingTry to get the first item x in the container xs and return Some(x) if exists. Return nothing if xs is empty.
Examples
julia> using Maybe
julia> Maybe.first([])
julia> Maybe.first([1])
Some(1)Maybe.get — FunctionMaybe.get(d, k) -> Some(x) or nothingTry to get an item x at key k and return Some(x) if found. Return nothing if not found.
It is more efficient than calling haskey(dict, key) and then dict[key] because it does not lookup the key twice.
Examples
julia> using Maybe
julia> Maybe.get(Dict(), :a)
julia> Maybe.get(Dict(:a => 1), :a)
Some(1)
julia> Maybe.get([1], 2)
julia> Maybe.get([1], 1)
Some(1)Maybe.getindex — FunctionMaybge.getindex(xs, indices...) -> Some(x) or nothingTry to get an item x at location specified by indices and return Some(x) if found. Return nothing if not found.
When xs is an array and Maybge.getindex is called inside @inbounds, it always try to return Some(x) without checking the bounds.
Examples
julia> using Maybe
julia> Maybe.getindex((11, 22, 33), 0)
julia> Maybe.getindex((11, 22, 33), 2)
Some(22)Maybe.getproperty — FunctionMaybe.getproperty(object, name) -> Some(property) or nothingReturn the property named name if object has it.
Examples
julia> using Maybe
julia> Maybe.getproperty((a = 1,), :b)
julia> Maybe.getproperty((a = 1,), :a)
Some(1)Maybe.last — FunctionMaybe.last(xs) -> Some(x) or nothingTry to get the last item x in the container xs and return Some(x) if exists. Return nothing if xs is empty.
Examples
julia> using Maybe
julia> Maybe.last([])
julia> Maybe.last([1])
Some(1)Maybe.length — FunctionMaybe.length(itr) -> Some(n::Integer) or nothingReturn the length of iterator if known.
Examples
julia> using Maybe
julia> Maybe.length(x for x in 1:3 if false)
julia> Maybe.length(1:3)
Some(3)Maybe.ok — FunctionMaybe.ok(Ok(x)) -> Some(x)
Maybe.ok(Err(_)) -> nothingReturn a Some by re-wrapping a value inside an Ok result; return nothing on an Err result.
See also Maybe.err.
Examples
julia> using Maybe, Try
julia> Maybe.ok(Ok(1))
Some(1)
julia> Maybe.ok(Err(1)) === nothing
trueMaybe.Extras
Maybe.Extras — ModuleMaybe.ExtrasA namespace for extra API; this is for preserving Maybe.* namespace for (mainly) Base-compatible API.
Since there is no name clash with Base API, using Maybe.Extras imports the API defined in Maybe.Extras.
Maybe.Extras.defaultto — FunctionMaybe.Extras.defaultto(x)A shorthand of ifnothing(() -> x).
Examples
julia> using Maybe.Extras
julia> Some(1) |> defaultto(:fallback)
1
julia> nothing |> defaultto(:fallback)
:fallbackMaybe.Extras.getnested — FunctionMaybe.Extras.getnested(x, k₁, k₂, ..., kₙ) -> v::Union{Some{T},Nothing}Try to get the item v = x[k₁][k₂][...][kₙ] and return Some(v); return nothing if the key does not exist.
Maybe.Extras.ifnothing — FunctionMaybe.Extras.ifnothing(f) -> x -> ifnothing(f, x)
Maybe.Extras.ifnothing(f, nothing) -> f()
Maybe.Extras.ifnothing(f, Some(x)) -> xSee also defaultto.
Examples
julia> using Maybe.Extras
julia> Some(1) |> ifnothing(() -> :fallback)
1
julia> nothing |> ifnothing(() -> :fallback)
:fallbackMaybe.Extras.maybe — Functionmaybe(f) -> f′Transform ("lift") function f(::T₁, ..., ::Tₙ) -> ::Union{Some{R}, R, Nothing} to f′(::Union{T₁, Some{T₁}, Nothing}, ..., ::Union{Tₙ, Some{Tₙ}, Nothing}) -> ::Union{Some{R}, Nothing}.
Examples
julia> using Maybe.Extras
julia> const ⊕ = maybe(+);
julia> 1 ⊕ nothing
julia> 1 ⊕ 2
Some(3)