🎓 A1Learner
🔍
0 of 48 lessons completed

Julia Macro Hygiene

Macro hygiene is the rule that keeps names a macro creates apart from the caller's names. Escaped names are the exception to that rule.

A macro name does not change the caller's variable

The macro creates a name of its own. The caller's x keeps its first value.

macro setlocal()
  return :(x = 50)
end
x = 1
println(@setlocal())
println(x)

An escaped name changes the caller's variable

Escaping marks a name as the caller's own name. The caller's x then takes the new value.

macro setcaller()
  return :($(esc(:x)) = 50)
end
x = 1
println(@setcaller())
println(x)

Gensym makes a fresh name each time

Two fresh names are never equal. That freshness stops a temporary name from clashing with a caller's name.

a = gensym(:tmp)
b = gensym(:tmp)
println(a == b)
println(typeof(a))

Example

macro setlocal()
  return :(x = 50)
end
macro setcaller()
  return :($(esc(:x)) = 50)
end
macro addtemp(ex)
  t = gensym(:t)
  return :($t = $(esc(ex)); 2 * $t)
end
x = 1
println(@setlocal())
println(x)
println(@setcaller())
println(x)
v = 6
println(@addtemp v)

Key points

  • Hygiene: names a macro creates stay separate from the caller's names.
  • Escape: use esc to mark a name as the caller's own name.
  • Gensym: gensym makes a fresh name that cannot clash with a caller's name.
  • Local name: a macro name without esc leaves the caller's value unchanged.
  • Caller name: an escaped name changes the caller's value.

In this example, the first macro leaves the caller's x at 1. The escaped macro then sets it to 50. The last macro uses gensym for a fresh temporary name to double 6.

Note

a fresh temporary name inside a macro keeps its work apart from the caller's names.

Try it Yourself

Edit the code, then press Run.

Running is simulated · JuliaHub

Exercise

A macro sets a name without esc, and the caller already has that name. What happens to the caller's value?