It might not be logically a part of hygiene features, but it’s a related one. The point is that macros in Julia are a bit more complicated than just substituting some text. In your first example:
temp = foo
Julia knows that the macro is defined in module
foo refers to
Foo.foo. Thus when you use this macro in another module, during macroexpand time Julia assigns
temp = Foo.foo and then evaluates
:($temp) in the context of that module:
temp = foo
x = eval(current_module(), :($temp))
# prints "Foo.foo"
Note how Julia conveniently found the correct object
foo from the scope of macro definition. It’s very similar to example with
time from hygiene section of manual I pointed to, even though
time is used in a returned expression while
foo is only used in body of the macro.
In your second example you don’t actually have any references to
Foo.foo, but just a symbol
:foo. For Julia symbol
:foo is just data, so it’s passed as is. During macroexpand time when you call
eval(current_module(), :(foo)) Julia tries to find a thing called
foo in the current module (
Main), but it’s not defined:
x = eval(current_module(), :(foo))
# ERROR: UndefVarError: foo not defined
Though, if you define
Main, it will work fine:
foo = "macroprogramming is awesome!"
# prints "macroprogramming is awesome!"