Closed
Description
I'd like to discuss the opportunity and possible implementations of a syntax similar to Swift's if let
. The idea is to offer a compact syntax to check whether a Nullable
is null, performing an action on its value if it isn't (with an optional fallback if it is).
This was mentioned recently on julia-users: https://groups.google.com/d/msg/julia-users/pgaw6VnBJ34/bBe2lJ1mAQAJ
I gave a try at writing a macro offering a similar feature in Julia, and as expected it can be made to work quite easily. There are a few issues to discuss, though:
- First, do people think it would be worth having in Base? I think making it easy to work with
Nullable
in a rigorous way is a major feature, and this seems to be a quite common opinion nowadays. @if let
cannot be used because of parsing issues. That's not a big deal IMO, as I'm not a fan of that naming choice. I've retained@unwrap if
, but we could find a better name (if
is required to allowelse
).- I've chosen to override the same variable binding using
let x=get(x)
(i.e. you access the value with the same name as theNullable
). I think this is clearer as there's no reason to need both variables in the same context, and it avoids prompting people to use artificially different names for the "same" thing. - I think an alternative solution to this ad-hoc macro would be extend the
do
syntax to allow for anelse
part, which would be implemented by passing two functions toget
(one for when a value is present, one for when it isn't). The advantage is that it could be useful in other places: for example to allow working efficiently with dicts, with code to update a value if found, and code returning a default value (?= "get or set" operator #2108).
So, here's the macro, and examples of how it can be used:
macro unwrap(ex)
if !isa(ex, Expr) || ex.head != :if
throw(ArgumentError("@unwrap expects an if or if...else block"))
end
x = esc(ex.args[1])
if length(ex.args) == 3
quote
if !isnull($x)
let $x = get($x)
$(esc(ex.args[2]))
end
else
$(esc(ex.args[3]))
end
end
else
quote
if !isnull($x)
let $x = get($x)
$(esc(ex.args[2]))
end
end
end
end
end
v = Nullable(1)
@unwrap if v
res = v + 1
end
@unwrap if v
res = v + 1
else
res = 0
end
Cc: @johnmyleswhite