# What's wrong with this macro?

**URL:** <https://discourse.julialang.org/t/whats-wrong-with-this-macro/49419>\
**Category:** General Usage\
**Created:** [November 1, 2020, 5:46pm UTC](https://discourse.julialang.org/t/whats-wrong-with-this-macro/49419 "2020-11-01T17:46:48Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![giancarloantonucci](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giancarloantonucci/32/202551_2.png) [@giancarloantonucci](https://discourse.julialang.org/u/giancarloantonucci)\
**Post date:** [November 1, 2020, 5:46pm UTC](https://discourse.julialang.org/t/whats-wrong-with-this-macro/49419/1 "2020-11-01T17:46:48Z")

</div>

In theory, I have a macro that allows me to interpret

```julia
@← a = f(b...)

```

as either

```julia
f!(a, b...)

```

or

```julia
a = f(b...)

```

depending on whether `f!` is defined or not. My attempt at writing such a macro is

```julia
macro ←(input)
    # expression needs to be of form `a = f(b...)`
    a = input.args[1]
    f = input.args[2].args[1]
    f! = Symbol(f, "!")
    b = input.args[2].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...))
        else
            error("ERROR!")
        end
    end
    esc(output)
end

```

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?

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [November 1, 2020, 6:23pm UTC](https://discourse.julialang.org/t/whats-wrong-with-this-macro/49419/2 "2020-11-01T18:23:53Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [November 1, 2020, 6:24pm UTC](https://discourse.julialang.org/t/whats-wrong-with-this-macro/49419/3 "2020-11-01T18:24:51Z")

</div>

BTW, do you know about [BangBang.jl](https://juliafolds.github.io/BangBang.jl/dev/)? It sounds like you are trying to achieve something very similar.

---

<div class="post-metadata">

**Author:** ![giancarloantonucci](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giancarloantonucci/32/202551_2.png) [@giancarloantonucci](https://discourse.julialang.org/u/giancarloantonucci)\
**Post date:** [November 1, 2020, 6:31pm UTC](https://discourse.julialang.org/t/whats-wrong-with-this-macro/49419/4 "2020-11-01T18:31:10Z")

</div>

> [@simeonschaub](#):
>
> I think, you probably meant to write `return $f!($a, $(b...))` instead of `return $f!($a, $b...)` .

You are completely right. However, the problem persists.

> [@simeonschaub](#):
>
> BTW, do you know about [BangBang.jl](https://juliafolds.github.io/BangBang.jl/dev/)? It sounds like you are trying to achieve something very similar.

I did not! Their macro `@!` is indeed doing something very similar. I’ll check that, thanks.

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [November 1, 2020, 6:35pm UTC](https://discourse.julialang.org/t/whats-wrong-with-this-macro/49419/5 "2020-11-01T18:35:04Z")

</div>

> [@giancarloantonucci](#):
>
> > [@simeonschaub](#):
> >
> > I think, you probably meant to write `return $f!($a, $(b...))` instead of `return $f!($a, $b...)` .
> 
> You are completely right. However, the problem persists.

Could you share a full example of how you are calling it? That usually makes it a lot easier to help you.

---

<div class="post-metadata">

**Author:** ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)\
**Post date:** [November 1, 2020, 7:03pm UTC](https://discourse.julialang.org/t/whats-wrong-with-this-macro/49419/6 "2020-11-01T19:03:21Z")

</div>

Is the problem that `isdefined` doesn’t handle local scope? [Essentials · The Julia Language](https://docs.julialang.org/en/v1/base/base/#Core.isdefined)

---

<div class="post-metadata">

**Author:** ![giancarloantonucci](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giancarloantonucci/32/202551_2.png) [@giancarloantonucci](https://discourse.julialang.org/u/giancarloantonucci)\
**Post date:** [November 1, 2020, 7:14pm UTC](https://discourse.julialang.org/t/whats-wrong-with-this-macro/49419/7 "2020-11-01T19:14:24Z")

</div>

I _think_ I’m doing something like

```julia
f(b) = [1, 1, 1]
function f!(a, b)
    a[1] = 2
    a[2] = 2
    a[3] = 2
    a
end
function g(v)
    @← v[1] = f("!@£%")
    v
end

v = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
g(v)

```

which, however, seems to work just fine.

In actual practice, when running the following snippet

```julia
using RungeKutta
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)
plot(solution)

```

which calls my package [RungeKutta.jl](https://github.com/antonuccig/RungeKutta.jl), I’m having trouble when changing from

```julia
f!(k[i], v, t[n] + h * c[i])

```

to

```julia
@← k[i] = f(v, t[n] + h * c[i])

```

lines 19-20 in [step.jl](https://github.com/antonuccig/RungeKutta.jl/blob/master/src/step.jl).

---

<div class="post-metadata">

**Author:** ![giancarloantonucci](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giancarloantonucci/32/202551_2.png) [@giancarloantonucci](https://discourse.julialang.org/u/giancarloantonucci)\
**Post date:** [November 1, 2020, 7:17pm UTC](https://discourse.julialang.org/t/whats-wrong-with-this-macro/49419/8 "2020-11-01T19:17:28Z")

</div>

> [@johnmyleswhite](#):
>
> Is the problem that `isdefined` doesn’t handle local scope?

It could very well be! Any alternative to `@isdefined` then?

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](https://discourse.julialang.org/t/check-whether-a-variable-is-defined/1018/3) 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`](https://docs.julialang.org/en/v1/base/base/#Base.@isdefined) instead of `Core.@isdefined`, which is able to deal with the current scope.

---

<div class="post-metadata">

**Author:** ![giancarloantonucci](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giancarloantonucci/32/202551_2.png) [@giancarloantonucci](https://discourse.julialang.org/u/giancarloantonucci)\
**Post date:** [November 2, 2020, 10:46am UTC](https://discourse.julialang.org/t/whats-wrong-with-this-macro/49419/9 "2020-11-02T10:46:44Z")

</div>

Getting rid of the `return`s solved the issue.
