7.4 Identifier used out of context
compile: identifier used out of context in: stuff
This occurs when a syntax template contains a reference to a locally-scoped name and the resulting syntax is later interpreted in a context outside of the scope of that name. The following examples illustrate how that can happen.
Usually the cause of this problem is a macro that has a local binding and a syntax template that refers to that local binding. Referring to such a local binding is illegal. Here’s a simple example:
> (define stuff 10) | |||||
| |||||
> (m 7) | |||||
eval:3:0: compile: identifier used out of context in: stuff |
The reference to stuff in the syntax template refers to the nearest enclosing binding of stuff, which is inside the macro. When (m 7) is expanded, it produces (+ 7 stuff). The new occurrence of stuff is outside of the scope of the stuff binding it refers to, and the macro expander raises an “identifier used out of context” error.
The problem is not simply a phase mismatch, although in the previous example the local binding was at phase 1 and the reference was compiled at phase 0. Here is an example where the binding and reference are at the same phase:
| |||||
> (def y) | |||||
eval:2:0: compile: identifier used out of context in: stuff |
The binding of stuff is at phase 1. The reference to stuff is at phase 1. But it’s still out of context.
The problem is not even because the binding only exists for the duration of the macro’s activation. Here’s an example of a local binding that outlives the macro transformation step; the macro’s output is still illegal.
| |||||||
> (def y) | |||||||
eval:2:0: compile: identifier used out of context in: stuff |
It is possible to trigger an “out of context” error by using eval also:
| ||
eval:2:0: compile: identifier used out of context in: stuff |
This code fails because eval interprets its argument as top-level code, so even though the call occurs inside of the stuff binding, the syntax is interpreted effectively outside of it.