# Simple question about macro arguments

**URL:** <https://discourse.julialang.org/t/simple-question-about-macro-arguments/125795>\
**Category:** New to Julia\
**Tags:** macros, metaprogramming\
**Created:** [February 11, 2025, 4:17pm UTC](https://discourse.julialang.org/t/simple-question-about-macro-arguments/125795 "2025-02-11T16:17:14Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ludovic\_Dumoulin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ludovic_dumoulin/32/22414_2.png) [@Ludovic\_Dumoulin](https://discourse.julialang.org/u/Ludovic_Dumoulin)\
**Post date:** [February 11, 2025, 4:17pm UTC](https://discourse.julialang.org/t/simple-question-about-macro-arguments/125795/1 "2025-02-11T16:17:14Z")

</div>

Hello,

I would like to use a macro to compute derivative of several fields.  
Concretly, in a simplified context, I have the following issue:  
for the macro

```julia
macro testij(i,j) esc(:(a[$i]=b[$j] )) end

```

for `a` and `b` defined, if I do `@macroexpand @testij(1+2,2)` I get

```julia
:(a[1 + 2] = b[2])

```

I would like to obtain this `:(a[3] = b[2])`, how can I do it ?

In my particular case I do operation on several field:

```julia
macro compute_∇P(li,lj) esc( 
    quote
        ∂xPx = (P_shared[$li+1,$lj,1] - P_shared[$li-1,$lj,1])*0.5/Δ
        ∂zPx = (P_shared[$li,$lj+1,1] - P_shared[$li,$lj-1,1])*0.5/Δ
        ∂xPz = (P_shared[$li+1,$lj,2] - P_shared[$li-1,$lj,2])*0.5/Δ
        ∂zPz = (P_shared[$li,$lj+1,2] - P_shared[$li,$lj-1,2])*0.5/Δ
    end)
end

```

For boundary conditions I do

```julia
i_ = mod(i-1,1:N)
@compute_∇P(i_,j)

```

but I would like to write it this way `@compute_∇P(mod(i-1,1:N),j)` without computing the modulus several time.

Thank you for your help,  
Best

---

<div class="post-metadata">

**Author:** ![matthias314](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@matthias314](https://discourse.julialang.org/u/matthias314)\
**Post date:** [February 11, 2025, 6:22pm UTC](https://discourse.julialang.org/t/simple-question-about-macro-arguments/125795/2 "2025-02-11T18:22:09Z")

</div>

If you write

```julia
macro compute_∇P(li, lj)
    quote
        let li = $li, lj = $lj
            lip, lim = li+1, li-1
            ljp, lim = lj+1, lj-1
            ∂xPx = (P_shared[lip, lj, 1] - P_shared[lim, lj, 1])*0.5/Δ
            ∂zPx = (P_shared[li, ljp, 1] - P_shared[li, ljm, 1])*0.5/Δ
            ∂xPz = (P_shared[lip, lj, 2] - P_shared[lim, lj, 2])*0.5/Δ
            ∂zPz = (P_shared[li, ljp, 2] - P_shared[li, ljm, 2])*0.5/Δ
        end
    end |> esc
end

```

then `li` and `lj` are evaluated only once:

```julia
julia> @macroexpand @compute_∇P(mod(i-1,1:N), j)
quote
    #= REPL[1]:3 =#
    let li = mod(i - 1, 1:N), lj = j
        #= REPL[1]:4 =#
        (lip, lim) = (li + 1, li - 1)
        #= REPL[1]:5 =#
        (ljp, lim) = (lj + 1, lj - 1)
        #= REPL[1]:6 =#
        ∂xPx = ((P_shared[lip, lj, 1] - P_shared[lim, lj, 1]) * 0.5) / Δ
        #= REPL[1]:7 =#
        ∂zPx = ((P_shared[li, ljp, 1] - P_shared[li, ljm, 1]) * 0.5) / Δ
        #= REPL[1]:8 =#
        ∂xPz = ((P_shared[lip, lj, 2] - P_shared[lim, lj, 2]) * 0.5) / Δ
        #= REPL[1]:9 =#
        ∂zPz = ((P_shared[li, ljp, 2] - P_shared[li, ljm, 2]) * 0.5) / Δ
    end
end

```

EDIT: Alternatively, why not use a function that returns the tuple `(∂xPx, ∂zPx, ∂xPz, ∂zPz)`?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [February 11, 2025, 6:56pm UTC](https://discourse.julialang.org/t/simple-question-about-macro-arguments/125795/3 "2025-02-11T18:56:32Z")

</div>

Macro calls don’t act when function calls do, they transform source code, so they have to act before the code is evaluated. Consequently, their inputs are only a few inlined literals (`Int`, `Float64`, `String`), `Symbol`, and `Expr` that are initially parsed from source code. That means the macro actually takes `i == :(1+2)`; it’s not like a function call where `1+2` evaluates beforehand. Instead, you need to generate code that evaluates `1+2` before its result is used for indexing. matthias314’s comment works off similar principles.

In the global scope, it is possible to normally `eval`-uate `Expr` interpolated with previously computed values of any type. Evaluation of arbitrary expressions can’t be done within local scopes after full parsing.

---

<div class="post-metadata">

**Author:** ![Ludovic\_Dumoulin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ludovic_dumoulin/32/22414_2.png) [@Ludovic\_Dumoulin](https://discourse.julialang.org/u/Ludovic_Dumoulin)\
**Post date:** [February 12, 2025, 10:12am UTC](https://discourse.julialang.org/t/simple-question-about-macro-arguments/125795/4 "2025-02-12T10:12:02Z")

</div>

Thank you for your help,  
It is amazing to have answers so fast !

> [@matthias314](#):
>
> EDIT: Alternatively, why not use a function that returns the tuple `(∂xPx, ∂zPx, ∂xPz, ∂zPz)`?

I wouldn’t know exactly how to do it in an optimized way, this bloc of code is used in two CUDA.jl kernels.  
My `P` field from the global memory is load into the shared memory, then I compute derivatives of `P` that I need for the next step in the same kernel.  
As I don’t have enough space and as I need `P` each time I need `∇P`, I don’t want to save `∇P` in the global memory (I am trying to reduce the number of access to the global memory).  
I need the value of `∇P` in two different kernels and I prefer to not copy-past the code, that why I went for macro.

I am a physicist by training and know almost nothing about good practice for writing code. In fact I don’t even know exactly what I am allowed to write in a kernel. I am slowly learning by doing benchmark for my specific system.

Thank you again for your help !

EDIT: it is in fact not working with `let` but if I use

```julia
macro compute_∇P(li,lj)
    quote
        li=$li; lj=$lj
        lip, lim = li+1, li-1
        ljp, ljm = lj+1, lj-1
        ∂xPx = (P_shared[lip,lj,1] - P_shared[lim,lj,1])*0.5/Δ
        ∂zPx = (P_shared[li,ljp,1] - P_shared[li,ljm,1])*0.5/Δ
        ∂xPz = (P_shared[lip,lj,2] - P_shared[lim,lj,2])*0.5/Δ
        ∂zPz = (P_shared[li,ljp,2] - P_shared[li,ljm,2])*0.5/Δ
    end |> esc
end

```

it is enough to not compute the modulus multiple times

---

<div class="post-metadata">

**Author:** ![Ludovic\_Dumoulin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ludovic_dumoulin/32/22414_2.png) [@Ludovic\_Dumoulin](https://discourse.julialang.org/u/Ludovic_Dumoulin)\
**Post date:** [February 12, 2025, 11:02am UTC](https://discourse.julialang.org/t/simple-question-about-macro-arguments/125795/5 "2025-02-12T11:02:14Z")

</div>

> [@Ludovic\_Dumoulin](#):
>
> `li=$li; lj=$lj`

The issue with this way is that I systematically do two operations while I might need to evaluate only one. For this one I might need to define 4 new variables while I might only need zero or one `li=$li; lj=$lj; i=$i; j=$j` if I have to do only one modulus.

```julia
macro load_ρμPv(li,lj,i,j) esc(
    quote
        v_shared[$li,$lj,1] = v[$i,$j,1]
        P_shared[$li,$lj,1] = P[$i,$j,1]
        v_shared[$li,$lj,2] = v[$i,$j,2]
        P_shared[$li,$lj,2] = P[$i,$j,2]
        μ_shared[$li,$lj] = μ[$i,$j]
        ρ_shared[$li,$lj] = ρ[$i,$j]
    end)
end

```

concretely I would like to call `@load_ρμPv(li,T+2,i,mod(j+1,1:N))` without having to write

```julia
jp = mod(j+1,1:N)
ljp = T+2
@load_ρμPv(li,ljp,i,jp)

```

it is mainly to make it easier to read and more compact.

---

<div class="post-metadata">

**Author:** ![matthias314](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@matthias314](https://discourse.julialang.org/u/matthias314)\
**Post date:** [February 12, 2025, 1:11pm UTC](https://discourse.julialang.org/t/simple-question-about-macro-arguments/125795/6 "2025-02-12T13:11:27Z")

</div>

> [@Ludovic\_Dumoulin](#):
>
> it is in fact not working with `let`

I forgot to declare the variables before the `let`. There was also a typo. This one should work:

```julia
macro compute_∇P(li, lj)
    quote
        ∂xPx, ∂zPx, ∂xPz, ∂zPz = let li = $li, lj = $lj
            lip, lim = li+1, li-1
            ljp, ljm = lj+1, lj-1
            ∂xPx = (P_shared[lip, lj, 1] - P_shared[lim, lj, 1])*0.5/Δ
            ∂zPx = (P_shared[li, ljp, 1] - P_shared[li, ljm, 1])*0.5/Δ
            ∂xPz = (P_shared[lip, lj, 2] - P_shared[lim, lj, 2])*0.5/Δ
            ∂zPz = (P_shared[li, ljp, 2] - P_shared[li, ljm, 2])*0.5/Δ
            ∂xPx, ∂zPx, ∂xPz, ∂zPz
        end
    end |> esc
end

```

I’m using `let` to avoid overwriting existing variables `li` and `lj`. This may not be a concern in your case. A different way to achieve this would be to use `gensym` to create new variable names.

---

<div class="post-metadata">

**Author:** ![Ludovic\_Dumoulin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ludovic_dumoulin/32/22414_2.png) [@Ludovic\_Dumoulin](https://discourse.julialang.org/u/Ludovic_Dumoulin)\
**Post date:** [February 12, 2025, 3:14pm UTC](https://discourse.julialang.org/t/simple-question-about-macro-arguments/125795/7 "2025-02-12T15:14:18Z")

</div>

Thank you for your help, it is working well now !
