# Looping within a quote block in a macro

**URL:** https://discourse.julialang.org/t/looping-within-a-quote-block-in-a-macro/126246
**Category:** General Usage
**Created:** [February 24, 2025, 1:10pm UTC](https://discourse.julialang.org/t/looping-within-a-quote-block-in-a-macro/126246 "2025-02-24T13:10:33Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Pablo\_Marchant](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablo_marchant/32/32828_2.png) [@Pablo\_Marchant](https://discourse.julialang.org/u/Pablo_Marchant)
#### Post date: [February 24, 2025, 1:10pm UTC](https://discourse.julialang.org/t/looping-within-a-quote-block-in-a-macro/126246/1 "2025-02-24T13:10:33Z")

</div>

Hi,

I have a bit of a beginner question regarding macros. I’m well aware that macros are tricky and in many cases can just be replaced by functions, but I think for one application I have they can significantly reduce boiler-plate and allow for significant user flexibility. But I’m struggling a bit to do things I think should be straightforward. A bit of a toy example I have is below:

```julia
macro example_macro(name, values)
    quote
        struct $name
            $(values.args[1])
            $(values.args[2])
        end
    end
end
@macroexpand @example_macro(MyStruct, [value1, value2])

```

This is meant to define a struct with a given name and with a set of fields that are defined by the user. Utility in here is that there is a lot of boiler plate code and functions that would be defined for this composite type and that only require knowing these names.

Issue with the above example is that I am explicitly extracting the two elements of the given array, while I would like to programatically loop over however many there are. This seems like a simple operation but I’m finding it tricky to find info on how to perform these kinds of operations from online resources (sorry if I missed something obvious). How one would go about doing this? I know I can manually build up the full expression I want, but I like how the `quote` block provides nice readability for the resulting code.

And again, I know meta-programming might not be the solution but just want to understand it better and learn how to use it to see if it can effectively serve me in some cases.

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [February 24, 2025, 3:06pm UTC](https://discourse.julialang.org/t/looping-within-a-quote-block-in-a-macro/126246/2 "2025-02-24T15:06:50Z")

</div>

For your example, this works, too:

```julia
struct $name
    $(values.args...)
end

```

---

<div class="post-metadata">

### Author: ![HanD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hand/32/213908_2.png) [@HanD](https://discourse.julialang.org/u/HanD)
#### Post date: [February 24, 2025, 4:35pm UTC](https://discourse.julialang.org/t/looping-within-a-quote-block-in-a-macro/126246/3 "2025-02-24T16:35:47Z")

</div>

In case of the toy example, what @jules suggested works. For a slightly more complicated scenario, where you want to do some processing on the individual arguments, it doesn’t. In this case, you have to dig a bit deeper, e.g.:

```julia
julia> macro example_macro(name, values...)
    fields = map(values) do value
        :($(value)::Any = nothing)
    end
    return quote
        @kwdef struct $(name)
            $(fields...)
        end
    end
end
@example_macro (macro with 1 method)

julia> @macroexpand @example_macro foo bar baz
quote
    #= REPL[3]:6 =#
    begin
        #= util.jl:612 =#
        begin
            $(Expr(:meta, :doc))
            struct foo
                #= REPL[3]:7 =#
                bar::Main.Any
                baz::Main.Any
            end
        end
        #= util.jl:613 =#
        function Main.foo(; bar = Main.nothing, baz = Main.nothing)
            #= REPL[3]:6 =#
            Main.foo(bar, baz)
        end
    end
end

```

Note that this is still a contrived example, but the key takeaway is that you need to construct the resulting expression bit by bit. Sometimes its easier to construct `Expr` values directly instead of fiddling with quote expressions and blocks. E.g., instead of `:($(value)::Any = nothing)` above, I could’ve written

```julia
    Expr(:(=), Expr(:(::), value, :Any), :nothing)

```

as well.

---

<div class="post-metadata">

### Author: ![Pablo\_Marchant](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablo_marchant/32/32828_2.png) [@Pablo\_Marchant](https://discourse.julialang.org/u/Pablo_Marchant)
#### Post date: [February 24, 2025, 5:04pm UTC](https://discourse.julialang.org/t/looping-within-a-quote-block-in-a-macro/126246/4 "2025-02-24T17:04:08Z")

</div>

Thanks, this is exactly what I was looking for!
