Looping within a quote block in a macro

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> 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

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

as well.

2 Likes