Clojure的符号文字are documented需要以非数字字符开头。这与Java标识符或数字文字语法无关--Clojure符号文字是clojure.lang.LispReader
的read
方法作为符号读入的内容,并且Clojure符号文字中允许使用许多字符,这些字符在Java标识符中不允许(例如-
,>
...;还有一种将这些转换成字符序列的方案,例如用于>
的用于互操作的_GT_
)。导致错误的直接原因是clojure.lang.LispReader/read
在看到一个数字后立即发送到readNumber
,并且无法“退出”。
为了完整性而进行的切题讨论。
请注意,如果您构建用手一个符号,你可以用它来命名VAR:
;; Clojure's intern serves a different purpose to CL's intern, see (doc intern)
user> (intern *ns* (symbol "1+") inc)
#'user/1+
user> ((ns-resolve *ns* (symbol "1+")) 1)
2
你甚至可以做时髦的东西一样
user> (eval `(defrecord ~(symbol "1foo") []))
user.1foo
user> user.1foo
user.1foo
user> (user.1foo.)
#:user.1foo{}
...这是当然完全是疯狂的,虽然也许没有那么多
user> (in-ns (symbol "1foo"))
#<Namespace 1foo>
1foo> (clojure.core/refer-clojure)
nil
1foo> (defrecord Foo [])
1foo.Foo
1foo> (in-ns 'user)
#<Namespace user>
user> (1foo.Foo.)
; Evaluation aborted. ;; can't do that
user> (eval `(new ~(symbol "1foo.Foo")))
#:1foo.Foo{}
我想如果有人坚持要这样做最终会碰到JVM的限制。这样做当然没有好的目的......无论如何,回到原来的问题,由1+
引起的错误与符号字面语法有关,该符号字面量语法仅对于存在合理“翻译”的程度而言是Java友好的。有名字的Clojure对象不太关心那些名称是否构造良好或其他,尽管使用时髦的名字是笨拙的,绝对不支持。
(而user.1foo
从上面的例子实际上是一个Java类 - 我有点惊讶地看到,这其中有实际工作,但在另一方面,我好像记得JVM内部的限制上的名字都应该比起Java那些要严格得多)
请注意,在Common Lisp中,一致性实现可能会将'1a'解析为数字,就像Clojure试图(甚至没有* * read-base *比10)。请参阅HyperSpec中潜在编号的条目:http://www.lispworks.com/documentation/HyperSpec/Body/02_caa.htm – 2010-08-02 14:57:45