# Help writing macro which returns an eval expression

**URL:** <https://discourse.julialang.org/t/help-writing-macro-which-returns-an-eval-expression/31046>\
**Category:** General Usage\
**Created:** [November 13, 2019, 4:05pm UTC](https://discourse.julialang.org/t/help-writing-macro-which-returns-an-eval-expression/31046 "2019-11-13T16:05:28Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [November 13, 2019, 4:05pm UTC](https://discourse.julialang.org/t/help-writing-macro-which-returns-an-eval-expression/31046/1 "2019-11-13T16:05:28Z")

</div>

I have a macro which is expected to return a `Core.eval` expression, in the line of:

```julia
macro foreach(f, arr)
  quote
    Core.eval( __module__ ,
    quote
      isempty($(esc(arr))) && return ""

      mapreduce(*, $(esc(arr))) do _s
        @show @ __MODULE__
        $f(_s) * "\n"
      end
    end)
  end
end

```

However, I don’t know how to escape the `arr` argument all the way into the nested quote, resulting in `ERROR: UndefVarError: arr not defined`.

Thanks!

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [November 13, 2019, 4:53pm UTC](https://discourse.julialang.org/t/help-writing-macro-which-returns-an-eval-expression/31046/2 "2019-11-13T16:53:31Z")

</div>

Maybe something like this, where the quoted expression is built first, then spliced into the macro result (I also had to replace ` __module__ ` with `@ __MODULE__ ` and to escape `f`):

```julia
macro foreach(f, arr)
    e = quote
        isempty($(esc(arr))) && return ""
        
        mapreduce(*, $(esc(arr))) do _s
            @show @ __MODULE__
            $(esc(f))(_s) * "\n"
        end
    end
    
    quote
        Core.eval(@ __MODULE__ , $e)
    end
end

```

This expands to:

```julia
julia> let
           fun(x) = "$x"
           x = [1,2,3]
           @macroexpand @foreach fun x
       end
quote
    #= REPL[1]:12 =#
    (Main.Core).eval(Main, begin
            #= REPL[1]:3 =#
            Main.isempty(x) && return ""
            #= REPL[1]:5 =#
            Main.mapreduce(Main.:*, x) do #1#_s
                #= REPL[1]:6 =#
                begin
                    Base.println("#= REPL[1]:6 =# @ __MODULE__ () = ", Base.repr(begin
                                #= show.jl:576 =#
                                #2#value = Main
                            end))
                    #2#value
                end
                #= REPL[1]:7 =#
                fun(#1#_s) * "\n"
            end
        end)
end

```

and seems to work at runtime too:

```julia
julia> let
           fun(x) = "$x"
           x = [1,2,3]
           @foreach fun x
       end
#= REPL[1]:6 =# @ __MODULE__ () = Main
#= REPL[1]:6 =# @ __MODULE__ () = Main
#= REPL[1]:6 =# @ __MODULE__ () = Main
"1\n2\n3\n"

```

(but I’m not sure this is what the macro was meant to do…)

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [November 13, 2019, 4:58pm UTC](https://discourse.julialang.org/t/help-writing-macro-which-returns-an-eval-expression/31046/3 "2019-11-13T16:58:52Z")

</div>

But I have to ask: why the `eval` stage, and not simply:

```julia
macro foreach(f, arr)
    quote
        isempty($(esc(arr))) && return ""

        mapreduce(*, $(esc(arr))) do _s
            @show @ __MODULE__
            $(esc(f))(_s) * "\n"
        end
    end
end

```

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [November 13, 2019, 5:12pm UTC](https://discourse.julialang.org/t/help-writing-macro-which-returns-an-eval-expression/31046/4 "2019-11-13T17:12:42Z")

</div>

Thanks!

I actually meant ` __module__ ` – as that’s the point of the macro, to obtain a reference to the module where it’s invoked.

As for the reason, it’s quite complex. The simple code you propose at the end is what I have been using for a while, but doesn’t work entirely. It’s for an HTML based templating language.

There’s a module called `Flax` which is part of an external package (`Genie`) which can read an HTML template file with embedded Julia code. `Flax` knows how to parse the HTML code and dynamically execute the Julia code in order to include parts of other views, add logic based of conditionals, loops, etc. Ultimately, it “executes” this code to generate the resulting HTML which is sent to the browser.

But these view files are defined and loaded into the user app, usually in a Controller module (or in some external Julia file). And `Flax` needs access to the variables from the view file, which are defined in the user file (in the Controller). So `Flax` evals the template in the Controller’s context, so the template code has access to the variables. It all works great with the exception of this `@foreach` macro, which because is a macro, does not get evaled within the Controller’s scope but within `Flax` itself.

Hence my need to grab ` __module__ ` (which is the Controller) and have the expression evaling in ` __module__ ` scope.

I hope that makes sense.

* * *

Example of a Flax template:

```nohighlight
<table class="table table-striped">
<% @foreach(@vars(:translations)) do t %>
    <tr>
      <td style="width: 45%" id="original_$(t.id)" data-action="original">$(t.original |> escapeHTML)</td>
      <td><button class="btn btn-outline-secondary btn-sm" title="Copy" data-action="copy">↪</button></td>
      <td style="width: 45%" data-action="editor">
        <textarea name="translation_$(t.id)" class="form-control">$( getfield(t, Symbol(@vars(:locale))) )</textarea>
      </td>
      <td><button class="btn btn-outline-secondary btn-sm" data-action="save">Save</button></td>
    </tr>
<% end %>
</table>

```

This works well, but the problem is, if there is a variable `x` defined outside the `@foreach` inner block, it’s not accessible inside the block, as the code runs in a different scope.

* * *

I will give the nested code a try, thank you!

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [November 13, 2019, 5:25pm UTC](https://discourse.julialang.org/t/help-writing-macro-which-returns-an-eval-expression/31046/5 "2019-11-13T17:25:03Z")

</div>

Thanks, I did not know about ` __module__ `… Is it documented somewhere ? Is it specific to Flax or Genie?

In any case, if you’re `eval`ing the code you produce in another module, how is that module going to access the data you provide to the macro (e.g. `arr`)?

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [November 13, 2019, 5:27pm UTC](https://discourse.julialang.org/t/help-writing-macro-which-returns-an-eval-expression/31046/6 "2019-11-13T17:27:12Z")

</div>

It’s Julia - the ` __module__ ` variable is automatically made available by Julia within the macro:  
[https://docs.julialang.org/en/v1/manual/metaprogramming/index.html#Macro-invocation-1](https://docs.julialang.org/en/v1/manual/metaprogramming/index.html#Macro-invocation-1)

* * *

If the view needs to access variables from the module, I just pass the module explicitly.

Ex:

```julia
julia> x = 100
julia> view = raw"<div>$x</div>"
julia> Genie.Render.html(view, context = @ __MODULE__ )

```

However, the preferred approach is to pass the variables explicitly, ie:

```julia
julia> view = raw"<div>$x</div>"
julia> Genie.Render.html(view, x = 100)

```

Both invocations work.

* * *

Update 1 - sorry, I meant ` __module__ ` not ` __macro__ ` - edited!

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [November 13, 2019, 6:07pm UTC](https://discourse.julialang.org/t/help-writing-macro-which-returns-an-eval-expression/31046/7 "2019-11-13T18:07:24Z")

</div>

@ffevotte Yes, victory, thank you!

All I had to do is introduce ` __module__ ` instead of `@ __MODULE__ `:

```julia
macro foreach(f, arr)
  e = quote
    isempty($(esc(arr))) && return ""

    mapreduce(*, $(esc(arr))) do _s
      @show @ __MODULE__
      $(esc(f))(_s)
    end
  end

  quote
    Core.eval($ __module__ , $e)
  end
end

```

Here is the code being used 🙂

* * *

```julia
julia> using Genie.Renderer

julia> y = 100
100 

julia> view = raw"""
       <ol>
       <% @foreach(["a", "b", "c"]) do letter %>
       <li>$(letter) $(y)</li>
       <% end %>
       </ol>"""
"<ol>\n<% @foreach([\"a\", \"b\", \"c\"]) do letter %>\n<li>\$(letter) \$(y)</li>\n<% end %>\n</ol>"

julia> html(view)
#= /Users/adrian/.julia/dev/Genie/src/Flax.jl:318 =# @ __MODULE__ () = Genie.Renderer
ERROR: UndefVarError: y not defined

julia> html(view, context = @ __MODULE__ )
#= /Users/adrian/.julia/dev/Genie/src/Flax.jl:318 =# @ __MODULE__ () = Main
HTTP.Messages.Response:
"""
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8

<html><head></head><body><ol><li>a 100</li><li>b 100</li><li>c 100</li></ol></body></html>"""

```

Great stuff, thanks so much!

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [November 13, 2019, 6:19pm UTC](https://discourse.julialang.org/t/help-writing-macro-which-returns-an-eval-expression/31046/8 "2019-11-13T18:19:03Z")

</div>

Thanks for the explanations about ` __module__ `. And glad I could be of help!
