It’s more of an ifelse
, since all its args are eagerly evaluated (think &
vs &&
, and why there is not an and
function equivalent to &&
). Use on real code™ can lead to significant penalty, if “else clause” args are computational intensive.
What about a macro variant @something
?
macro something(x, y...)
:(let x_ = $(esc(x)) ;
if x_ isa Nothing; (@something $(y...))
elseif x_ isa Some; x_.value
else; x_
end
end)
end
macro something()
:(throw(ArgumentError("No value arguments present")))
end
tested by
using Test
# testing v1 - no regression
@test (@something nothing 1) == 1
@test (@something(Some(1), nothing)) == 1
@test (@something(missing, nothing)) === missing
@test_throws ArgumentError @something(nothing, nothing)
# testing v2 now
const A_CALLS = Ref{Int}(0)
struct A
val
A(a) = begin; global A_CALLS; A_CALLS[]+=1; new(a) end
end
# ... with better peanut butter
@test A_CALLS[] == 0
a1 = A(1)
@test A_CALLS[] == 1
@test (@something 1 A(1)) == 1 # A(1) not called since it's unnecessary
@test A_CALLS[] == 1
# ... meanwhile, once upon a time
A_CALLS[] = 0 # reset
@test something(1, A(1)) == 1
@test_broken A_CALLS[] == 0
@test A_CALLS[] == 1 # a new A has been called inadvertently with the new legacy o: one
Should this deserve a PR