# How to properly import a macro inside a begin-end block

**URL:** https://discourse.julialang.org/t/how-to-properly-import-a-macro-inside-a-begin-end-block/106037
**Category:** General Usage
**Tags:** macros
**Created:** [November 10, 2023, 3:08pm UTC](https://discourse.julialang.org/t/how-to-properly-import-a-macro-inside-a-begin-end-block/106037 "2023-11-10T15:08:26Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![schlichtanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schlichtanders/32/32145_2.png) [@schlichtanders](https://discourse.julialang.org/u/schlichtanders)
#### Post date: [November 10, 2023, 3:08pm UTC](https://discourse.julialang.org/t/how-to-properly-import-a-macro-inside-a-begin-end-block/106037/1 "2023-11-10T15:08:26Z")

</div>

Hi there, I am very surprised that the following fails in Julia 1.9

```julia
julia> begin
           import Crayons: Crayon, @crayon_str
           f() = crayon"dark_gray"
       end
ERROR: UndefVarError: `@crayon_str` not defined

```

I want to run this on a remote and want to have a general begin/end around to enable the use of local variables.

How can I twist julia to properly import the str macro?

---

<div class="post-metadata">

### Author: ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)
#### Post date: [November 10, 2023, 4:26pm UTC](https://discourse.julialang.org/t/how-to-properly-import-a-macro-inside-a-begin-end-block/106037/2 "2023-11-10T16:26:16Z")

</div>

You need two blocks – macros are expanded before any code is run. See [JuliaLang/julia#46478](https://github.com/JuliaLang/julia/issues/46478) for some related discussion.

---

<div class="post-metadata">

### Author: ![schlichtanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schlichtanders/32/32145_2.png) [@schlichtanders](https://discourse.julialang.org/u/schlichtanders)
#### Post date: [November 10, 2023, 4:45pm UTC](https://discourse.julialang.org/t/how-to-properly-import-a-macro-inside-a-begin-end-block/106037/3 "2023-11-10T16:45:33Z")

</div>

thank you. not a great solution, but at least it is clear what works and what not.

---

<div class="post-metadata">

### Author: ![schlichtanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schlichtanders/32/32145_2.png) [@schlichtanders](https://discourse.julialang.org/u/schlichtanders)
#### Post date: [November 11, 2023, 8:54am UTC](https://discourse.julialang.org/t/how-to-properly-import-a-macro-inside-a-begin-end-block/106037/4 "2023-11-11T08:54:06Z")

</div>

I found an alternative workaround which does not need two code blocks: **using `@macroexpand` explicitly**

```julia
julia> begin
           import Crayons: Crayon, @crayon_str
           f() = @macroexpand crayon"dark_gray"
       end
f (generic function with 1 method)

julia> f()
\e[90m

```

---

<div class="post-metadata">

### Author: ![schlichtanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schlichtanders/32/32145_2.png) [@schlichtanders](https://discourse.julialang.org/u/schlichtanders)
#### Post date: [November 11, 2023, 8:56am UTC](https://discourse.julialang.org/t/how-to-properly-import-a-macro-inside-a-begin-end-block/106037/5 "2023-11-11T08:56:56Z")

</div>

I guess it is a special case here, as string macros usually return values and no expressions.

---

<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: [November 11, 2023, 11:26am UTC](https://discourse.julialang.org/t/how-to-properly-import-a-macro-inside-a-begin-end-block/106037/6 "2023-11-11T11:26:19Z")

</div>

You effectively delayed the expansion of `@crayon_str` because `@macroexpand` expands to a call on an input expression:

```julia
julia> @macroexpand begin
         import Crayons: Crayon, @crayon_str
         f() = @macroexpand crayon"dark_gray"
       end
quote
    #= REPL[13]:2 =#
    import Crayons: Crayon, @crayon_str
    #= REPL[13]:3 =#
    f() = begin
            #= REPL[13]:3 =#
            Base.macroexpand(Main, $(QuoteNode(:(crayon"dark_gray"))), recursive = true)
        end
end

```

However, the expand call is inside the `function` block, and it’s not constant folded so it got delayed to the method calls:

```julia
julia> @code_warntype f()
MethodInstance for f()
  from f() in Main at REPL[1]:3
Arguments
  #self#::Core.Const(f)
Body::Any
1 ─ %1 = (:recursive,)::Core.Const((:recursive,))
│ %2 = Core.apply_type(Core.NamedTuple, %1)::Core.Const(NamedTuple{(:recursive,)})
│ %3 = Core.tuple(true)::Core.Const((true,))
│ %4 = (%2)(%3)::Core.Const((recursive = true,))
│ %5 = Core.kwfunc(Base.macroexpand)::Core.Const(Base.var"#macroexpand##kw"())
│ %6 = (%5)(%4, Base.macroexpand, Main, $(QuoteNode(:(crayon"dark_gray"))))::Any
└── return %6

```

Another workaround is to run the import statement before the `begin` block is parsed, nesting it by interpolating an `@eval` call:

```julia
julia> @eval begin # fresh REPL session
         $(import Crayons: Crayon, @crayon_str) # $(nothing)
         f() = crayon"dark_gray"
       end
f (generic function with 1 method)

julia> @code_warntype f()
MethodInstance for f()
  from f() in Main at REPL[1]:3
Arguments
  #self#::Core.Const(f)
Body::Crayon
1 ─ return \e[90m

```

This is also how I like to compute constants without declaring `const` globals before nesting them in an expression, e.g. `@eval log5(x) = log2(x)/$(log2(5))` (that is not a good example because it’s simple enough for the compiler to constant fold). Still, I personally prefer running the import statements separately, inserting text ruins the point of copy and pasting into `begin` blocks in the REPL.

---

<div class="post-metadata">

### Author: ![schlichtanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schlichtanders/32/32145_2.png) [@schlichtanders](https://discourse.julialang.org/u/schlichtanders)
#### Post date: [November 12, 2023, 7:09pm UTC](https://discourse.julialang.org/t/how-to-properly-import-a-macro-inside-a-begin-end-block/106037/7 "2023-11-12T19:09:42Z")

</div>

nice workaround. I am curious whether this also works for Distributed, i.e. whether the Module and/or macro can be easily serialized. (At least it is probably not the recommended way to send full modules over the wire).

(My concrete case is about Pluto, i.e. I am using Malt.jl actually, currently in Distributed-fallback-mode)
