[CLJ-1051] Recursive function raises "call unbound fn" exception Created: 27/Aug/12 Updated: 01/Mar/13 Resolved: 09/Nov/12
|Affects Version/s:||Release 1.4|
I've tried to reduce the code to the minimum that will reproduce the problem. This is a parser combinator library that uses the "list of successes" method. The test is a simple expression for adding one-digit integers with support for parens; sample input might be "1+(2+3)+4".
Having declared the parsers (see attached file), the expression parser is this:
With the above, I get this error:
I can, however, avoid this error if I code the (factor) function by expanding the code of the parser (between):
And now I can do:
The ability to reuse parser and add conveniences like (between) is key for this style of parsing.
|Comment by Kevin Downey [ 27/Aug/12 6:03 PM ]|
this is not a bug in clojure.
declare creates an unbound var then your def tries to use the value of the var before you have given it a value.
declare does not let you use a value of a var before you have given it one (via def or whatever).
|Comment by Kevin Downey [ 27/Aug/12 6:05 PM ]|
|Comment by Armando Blancas [ 27/Aug/12 10:28 PM ]|
Thanks for looking into this.
Just want to point out that as far as the declare and the use of expr as a forward reference, the second scenario I've presented (with factor*) uses (declare) the same way, yet it works: the var "expr" in (factor*) ends up pointing to the root value set later, but before it runs.
Seems to me similar to this case, where f is defined in terms of itself and it works fine, having the var "f" obtained its root binding after the def form runs:
Given that I've got a usage that works, I would suspect that there's something about the first case that prevents the root binding to be visible to the declared var.
|Comment by Kevin Downey [ 28/Aug/12 3:25 AM ]|
the formatting of the second case makes it hard to read, but it looks like expr is referenced inside a function, so the var #'expr will not be derefed until the function is run.
|Comment by Armando Blancas [ 28/Aug/12 12:32 PM ]|
Though the difference isn't quite apparent to me, I kind of grasp the idea that the var may be in one case deref'ed earlier in one case than the other because calls to (bind) are eager and in the case of the additional call to (between) the var is inside the function. I'll ask the board for advice on this and this ticket can be closed. Thanks.
|Comment by Stuart Sierra [ 09/Nov/12 8:51 AM ]|
Closed based on discussion in comments.