2010-08-02 19 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那些要嚴格得多)