Details
-
Type:
Defect
-
Status:
Closed
-
Priority:
Major
-
Resolution: Declined
-
Affects Version/s: Release 1.4
-
Fix Version/s: None
-
Component/s: None
-
Labels:None
-
Environment:OSX
Description
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:
(declare expr)
(def factor
(choice (between (match \() (match \)) expr)
integer))
(def expr
(bind factor
(fn [t]
(choice (bind (match \+) (fn [_] (bind expr (fn [e] (result (+ t e))))))
(result t)))))
With the above, I get this error:
Clojure 1.4.0 user=> (load-file "expr.clj") #'user/expr user=> (run expr "(3)") IllegalStateException Attempting to call unbound fn: #'user/expr clojure.lang.Var$Unbound.throwArity (Var.java:43)
I can, however, avoid this error if I code the (factor) function by expanding the code of the parser (between):
(declare expr)
(def factor*
(choice (bind (match \() (fn [_]
(bind expr (fn [e]
(bind (match \)) (fn [_] (result e)))))))
integer))
(def expr
(bind factor*
(fn [t]
(choice (bind (match \+) (fn [_] (bind expr (fn [e] (result (+ t e))))))
(result t)))))
And now I can do:
Clojure 1.4.0 user=> (load-file "expr.clj") #'user/expr user=> (run expr "(3)") 3 user=> (run expr "1+(2+3)+(4+5)") 15
The ability to reuse parser and add conveniences like (between) is key for this style of parsing.
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).