2010-08-02 17 views
4

Common Lisp中我可以这样做:有意识的Clojure符号名称限制还是继承?

(setf a1 'a) 
(setf 1a 'b) 

Clojure中,我可以做的第一(忽略的事实是SETF和DEF的工作方式不同)

(def a1 'a) 

,但与第二我得到一个错误

(def 1a 'b) 

java.lang.NumberFormatException: Invalid number: 1a 

Clojure刚刚从Java继承了这个限制吗,还是它是故意的? (也就是说,你不能拥有带这种风格的Java的类名称,变量或方法名称 - 所以我认为它只是继续)。

+1

请注意,在Common Lisp中,一致性实现可能会将'1a'解析为数字,就像Clojure试图(甚至没有* * read-base *比10)。请参阅HyperSpec中潜在编号的条目:http://www.lispworks.com/documentation/HyperSpec/Body/02_caa.htm – 2010-08-02 14:57:45

回答

11

Clojure的符号文字are documented需要以非数字字符开头。这与Java标识符或数字文字语法无关--Clojure符号文字是clojure.lang.LispReaderread方法作为符号读入的内容,并且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那些要严格得多)