Should this live in Missings.jl? Potentially cleaner and easier to maintain than a skipmissing keyword argument in more functions.
Note that it uses postwalk so @mfalse can act recursively on nested expressions.
julia> using MacroTools
julia> function mfalse_helper(ex::Expr)
MacroTools.postwalk(ex) do x
if x isa Expr && x.head == :if
x.args[1] = wrap_coalesce(x.args[1])
elseif x isa Expr && x.head == :&&
x.args = wrap_coalesce.(x.args)
elseif x isa Expr && x.head == :||
x.args = wrap_coalesce.(x.args)
end
x
end
end;
julia> wrap_coalesce(x::Expr) = :(coalesce($x, false));
julia> wrap_coalesce(x::Symbol) = :(coalesce($x, false));
julia> wrap_coalesce(x) = x;
julia> macro mfalse(x)
esc(mfalse_helper(x))
end;
julia> x = missing;
julia> x == 1 ? 2 : 3
ERROR: TypeError: non-boolean (Missing) used in boolean context
Stacktrace:
[1] top-level scope
@ REPL[21]:1
julia> @mfalse x == 1 ? 2 : 3
3
Now that .|| and .&& are in Base, we can also account for these in the macro.
Should this live in Missings.jl? Potentially cleaner and easier to maintain than a
skipmissingkeyword argument in more functions.Note that it uses
postwalkso@mfalsecan act recursively on nested expressions.Now that
.||and.&&are in Base, we can also account for these in the macro.