In theory, I have a macro that allows me to interpret
@← a = f(b...)
a = f(b...)
depending on whether
f! is defined or not. My attempt at writing such a macro is
# expression needs to be of form `a = f(b...)`
a = input.args
f = input.args.args
f! = Symbol(f, "!")
b = input.args.args[2:end]
output = quote
if (@isdefined $f!) && isa($f!, Function)
return $f!($a, $(b...))
elseif (@isdefined $f) && isa($f, Function)
return $a = $f($(b...))
However, it does not seem to work as it should whenever I’m using it in local scope (e.g. some kind of function, etc.). Any idea why?
I think, you probably meant to write
return $f!($a, $(b...)) instead of
return $f!($a, $b...). The latter interpolates
Any[:(b...)] as a literal into the function call and then that gets splatted at runtime into
$f!, so you are effectively calling
f!(a, :(b...)). If you add the parentheses, the array is actually splatted into the expression tree.
BTW, do you know about BangBang.jl? It sounds like you are trying to achieve something very similar.
You are completely right. However, the problem persists.
I did not! Their macro
@! is indeed doing something very similar. I’ll check that, thanks.
Could you share a full example of how you are calling it? That usually makes it a lot easier to help you.
Is the problem that
isdefined doesn’t handle local scope? https://docs.julialang.org/en/v1/base/base/#Core.isdefined
I think I’m doing something like
f(b) = [1, 1, 1]
function f!(a, b)
a = 2
a = 2
a = 2
@← v = f("!@£%")
v = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
which, however, seems to work just fine.
In actual practice, when running the following snippet
u0 = [2.0; 3.0; -14.0]
tspan = (0.0, 1.0)
problem = Lorenz(u0, tspan)
solver = Euler(h = 1e-3)
solution = solve(problem, solver)
which calls my package RungeKutta.jl, I’m having trouble when changing from
f!(k[i], v, t[n] + h * c[i])
@← k[i] = f(v, t[n] + h * c[i])
lines 19-20 in step.jl.
It could very well be! Any alternative to
EDIT: I’ve changed
@isdefined with a custom one from https://discourse.julialang.org/t/check-whether-a-variable-is-defined/1018/3?u=jlapeyre which should work in local scope too, but, once again, without success.
EDIT 2: It turns out that, in this case, Julia correctly uses
Base.@isdefined instead of
Core.@isdefined, which is able to deal with the current scope.
Getting rid of the
returns solved the issue.