Scope of quote in IEX

I’ve been using quote and unquote in iex to experiment with it in unambiguous settings.

I’d appreciate help understanding the following error:

iex(79)> pp = 5
5
iex(80)> g = quote do: pp
{:pp, [], Elixir}
iex(81)> Code.eval_quoted g
error: undefined variable "pp" (context Elixir)
└─ nofile:1

** (CompileError) cannot compile code (errors have been logged)
iex(81)> Code.eval_quoted {:pp, [], Elixir}
error: undefined variable "pp" (context Elixir)
└─ nofile:1
iex(81)> Macro.expand pp, Elixir
5
iex(82)>

This is all in an attempt to understand quote block scoping when used in macros and how ambiguity can arise.

Generally, in hygienic settings, the errors I encounter with improper use of unquote indicate that the variable to be unquoted must be defined in the quote in order to ensure that the appropriate context is applied; however when I manually match a 3 element tuple, describing a variable with the correct context to say, variable b, outside of the quote block and then try to unquote it inside the quote block use Code.eval_quoted on it, I still get an undefined variable error.

Even if I unquote use the AST description directly within the quote block, without use of a matched variable, I get the same error; this is even if I first match the variable being described to a primitive outside of the quote block as shown in the above example.

You can read about macro hygiene here: Macros — Elixir v1.16.2

Shortly on your problem, if you want to access variables that are not in the scope of quote, you have to use var!/2.

2 Likes

Thanks for answering @D4no0 .

I thought that var! was only for allowing me to change the value of the variable outside of scope, such that its value outside of quote’s scope changed, not that I needed it to use the variables value at all. I did not know that the scope of quote was that isolated, but this fact has become apparent to me while experimenting.

I appreciate the confirmation.

Just for clarity, Code.eval_quoted is failing because the AST fragment does not itself contain all relevant variable descriptions and Code.eval_quoted will not check for corresponding variables outside of the scope of quote?

To be fair I am not 100% positive, as I never used this feature. I think of it as a security feature that would not allow the injected code to manipulate or inspect existing values, this can become a quite nice vector of attack from a library.

1 Like