# Lexically Scoped Macros?

**URL:** <https://discourse.julialang.org/t/lexically-scoped-macros/6835>\
**Category:** Internals & Design\
**Tags:** question, proposal\
**Created:** [November 1, 2017, 9:03pm UTC](https://discourse.julialang.org/t/lexically-scoped-macros/6835 "2017-11-01T21:03:28Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [November 1, 2017, 9:03pm UTC](https://discourse.julialang.org/t/lexically-scoped-macros/6835/1 "2017-11-01T21:03:28Z")

</div>

Hi, I recently had [a conversation](https://www.reddit.com/r/lisp/comments/7961z9/are_there_any_new_interesting_lisps_being/dp02ccl/) on the lisp subreddit where I was convinced that allowing for lexically scoped macros would be a potentially interesting and useful addition to Julia.

My questions are

- Why aren’t lexically scoped macros allowed?
- Is there a possibility of implementing them in the future along with an option to pass an environment parameter to the macro expander?

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [November 2, 2017, 4:32pm UTC](https://discourse.julialang.org/t/lexically-scoped-macros/6835/2 "2017-11-02T16:32:12Z")

</div>

I heard from someone [here](https://www.reddit.com/r/lisp/comments/7961z9/are_there_any_new_interesting_lisps_being/dp6hoav/) that Lexical macros were excluded for performance reasons as they make it “impossible to statically analyse the code and generate fast code”. This makes no sense to me as lexically scoping the macro should only serve to further localize its effects and should be converted to proper code at before compilation so I fail to see any problem.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [November 2, 2017, 4:40pm UTC](https://discourse.julialang.org/t/lexically-scoped-macros/6835/3 "2017-11-02T16:40:32Z")

</div>

I haven’t done any work in Lisp, but I tried reading the docs on lexically scoped macros. I’m having trouble understanding how they’re different from the macro hygiene that Julia already does by default: [https://docs.julialang.org/en/stable/manual/metaprogramming/#Hygiene-1](https://docs.julialang.org/en/stable/manual/metaprogramming/#Hygiene-1)

Do you have a sense of what a lexically scoped macro could do that Julia macros can’t?

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [November 2, 2017, 4:59pm UTC](https://discourse.julialang.org/t/lexically-scoped-macros/6835/4 "2017-11-02T16:59:28Z")

</div>

> I’m having trouble understanding how they’re different from the macro hygiene that Julia already does by default

Macros in Julia are only allowed to be defined in the global scope. What this means is that I am not allowed to build a function or macro which defines a macro:

```julia
julia> function make_greeting_macro(greeting)
           macro geet(name)
                  return :( println(greeting, $name) )
           end
       end
ERROR: syntax: macro definition not allowed inside a local scope

```

Wanting to make macros or functions that make macros is a pretty rare use case but its not unimaginable.

> Do you have a sense of what a lexically scoped macro could do that Julia macros can’t?

In the thread I linked to in my original post, the lisper who replied to me showed a neat macro he made which is passed a function and a list of symbols. The macro then returns the original list with the specified function applied only to the variables which were _unbound_.

I doubt such functionality is impossible to replicate in Julia but it certainly is impossible the way he did it. His macro works by defining a new macro in that local context which is passed an _environment variable_ which contains information about the local scope and the variables which are defined there.

To be clear, I don’t really know how useful these lexical macros actually are but I’d like to understand why we don’t allow them and if there isn’t a good reason to allow them I think they should be allowed even if we can’t currently divine a super critical use for them right now.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 2, 2017, 5:09pm UTC](https://discourse.julialang.org/t/lexically-scoped-macros/6835/5 "2017-11-02T17:09:05Z")

</div>

My guess would be that local macros are not _a priori_ incompatible with Julia, but adding them is not a high enough priority at the moment to justify the work.

I end up _writing_ macros much less than I did in Common Lisp. In CL, the argument is that you can do anything with macros, but from another perspective, sometimes you _have to_ use macros to paper over cracks of the language (with a standard that was frozen decades ago, etc). I _use_ great macro libraries written by others (eg [Parameters.jl](https://github.com/mauro3/Parameters.jl), [MacroTools.jl](https://github.com/MikeInnes/MacroTools.jl)), but my answer to the “do I really need a macro” question is frequently _no_, much more than in CL.

I find that generated functions are extremely powerful and work fine for many of the use cases I would have used lexical macros before.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [November 2, 2017, 5:11pm UTC](https://discourse.julialang.org/t/lexically-scoped-macros/6835/6 "2017-11-02T17:11:15Z")

</div>

> [@Mason](#):
>
> What this means is that I am not allowed to build a … macro which defines a macro:

Macros can make macros (albeit still in global scope).

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [November 2, 2017, 6:35pm UTC](https://discourse.julialang.org/t/lexically-scoped-macros/6835/7 "2017-11-02T18:35:18Z")

</div>

Got it, thanks. I suppose I can see how that might be useful, but, as @Tamas_Papp says, I’ve generally found that passing and returning functions is a better solution for my use cases. So I would do:

```julia
function make_greeting(greeting)
  function greet(name)
    println(greeting, name)
  end
end

```

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [November 2, 2017, 8:17pm UTC](https://discourse.julialang.org/t/lexically-scoped-macros/6835/8 "2017-11-02T20:17:19Z")

</div>

yes, I suspect you’re probably right and that this feature isn’t badly needed and so isn’t really worth the development time. I was mostly curious about if there was any performance reason or something why it’s not reasonable to define macros outside the global scope.

Out of curiosity, do you think that it’s possible to make a macro which lets one make a lexical macro? Like some macro `@lexical_macro` such thatcher following:

```julia
Function foo()
    @lexical_macro bar()
        ...
    End
End

```

Is allowed and @bar only exists inside the function foo?

I was thinking this might be a fun project for me to try and puzzle out but I’m not sure how to start.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [November 2, 2017, 8:28pm UTC](https://discourse.julialang.org/t/lexically-scoped-macros/6835/9 "2017-11-02T20:28:56Z")

</div>

Obviously for the silly example I used there is no reason to use a macro anywhere. That does not mean in principal that a function will always do the job you want a macro to do though. I get that this is probably an extremely niche thing though.
