unbound identifier error
#233
Closed
opened 4 years ago by Srdgh
·
10 comments
Loading…
Reference in New Issue
There is no content yet.
Delete Branch '%!s(<nil>)'
Deleting a branch is permanent. It CANNOT be undone. Continue?
I have been using pollen, almost daily, for a year now -- thank you for this simple and versatile tool.
This morning,
raco pollen render
yielded anunbound identifier
error. (The same command on the same file worked the day before.)This looked similar to #28, so I updated, including dependencies (
raco pkg update --update-deps pollen
). However, the problem remains. I have pasted the entire error message below, but please do let me know if any further information might help.Thank you in advance for any idea you might have on what is going wrong.
[Linux, Racket 7.8-1]
Is it still working for other
.poly.pm
files in the same project?Do you have a
setup
module in yourpollen.rkt
? Have you changed it lately?Thanks for the swift response.
I don't have other
.poly.pm
files in the same project, but the same thing happened for another.poly.pm
file in another directory.My setup module is as follows:
Puzzling! Can you create a new, minimal
.poly.pm
file in the same directory and reproduce the error when rendering it? Or would you mind posting the original.poly.pm
file?Thanks again. I just got the same error with a file named
test.poly.pm
in the same folder. Here are its contents:Can you point us to the repo that hosts your code?
Unfortunately, it is not public (and would take a lot of cleaning up before being ready).
However, it looks like the backtick in the following line in my
pollen.rkt
was the culprit. Removing this line solved the issue.(On the other hand, escaping the backtick with a backslash yields:)
Apologies if I am simply revealing my ignorance of a facet of Racket here. Thanks again to both of you.
OK I can reproduce it now. This is interesting. It’s not the backtick, but rather the name of your function:
quote
is the name of a very basic form in Racket. As a meta-language tool, Racket will happily let you re-define (“shadow”) any of its built-in functions and macros, but you will get unexpected behavior if you don’t fully understand what you’re doing.As explained in the linked docs, when Racket sees
'symbol
it interprets it as(quote symbol)
which would in turn normally use thequote
macro fromracket/base
. But now it would use thequote
from yourpollen.rkt
. (More on this in a bit)Two reasons this is interesting:
I’m actually kind of surprised this hasn’t come up before now, since when designing markup it makes complete sense to use the name
quote
to quote some text.Given this, I’m now curious how your pages ever worked! Did you add this function recently?
More technical info: This is just me trying to figure out why you go the particular error you did.
Behind the scenes, when your
.poly.pm
file is run, it first goes through an expander phase, where any macro forms are replaced with the results of running the macro functions on their contents.If you open a
.poly.pm
file and click the Macro Stepper you’ll see what this particular program (your documents are programs after all) looks like to Racket after it has expanded Pollen’s macros but before expanding any macros local to your file:If you click the Step button, you’ll see expansion goes fine until it gets to the
metas
submodule which in turnrequire
s thepollen-module
submodule. This evidently forces Racket to fully evaluate the code in that module, at whih point it encounters'markup
. Racket interprets this as(quote markup)
which would normally just leave a symbol there that the code inpollen/private/main-base
will look for to know what “mode” this file is (i.e. markdown, markup, pagetree, etc).But apparently, already at this stage the
quote
function defined in yourpollen.rkt
holds sway, and when Racket evaluates(quote markup)
it now expectsmarkup
to be a bound identifier just as it would in any other function call. Because it’s not, it fails and you get the error.What I’m unclear on is why the definitions in
pollen.rkt
matter at this stage.'markup
is inserted by the Pollen reader here but any bindings there are stripped out by the reader, soquote
can’t be bound to thepollen.rkt
version at that point. The expander for the module ispollen-module-begin
but I’m not sure quite how bindings frompollen.rkt
are affecting the'markup
at the beginning of that macro.A technique called partial expansion ensures that all forms in the parse tree that might introduce bindings (like
require
) have been discovered before expanding the other forms — because of course, those bindings will affect how those other forms should be expanded. Matthew Flatt describes it here.In this case, even though the
quote
binding in"pollen.rkt"
appears later in the source, it gets handled during the partial-expansion pass. Then Racket, now wielding the unintentionally redefinedquote
, goes back and evalutes the'markup
expression at the top, which has been read into the parse tree as(quote markup)
.Thank you both for these (very interesting) explanations. I learned Racket in order to use Pollen (and chose Pollen partially because I wanted to explore a Lisp), so "if you don’t fully understand what you’re doing" certainly applies.
To answer your question, Joel, (I now realise that) this only cropped up at this point because I just renamed the function from
inline-quotation
toquote
. I didn't realise that that was the problem because in the very same edit I introduced the backticks, having used apostrophes till then.I appreciate the detail of your explanation -- in future I'll try to avoid such 'reserved words'.