有意识的Clojure符号名称限制还是继承?

时间:2010-08-02 09:09:14

标签: java clojure jvm

在共同的LISP中,我可以做到:

(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 个答案:

答案 0 :(得分:11)

Clojure的符号文字are documented需要以非数字字符开头。这与Java标识符或数字文字语法无关 - Clojure符号文字是clojure.lang.LispReader的{​​{1}}方法作为符号读入的内容,并且在Clojure符号文字中允许有许多字符,在Java标识符中不允许使用(例如read- ...;还有一种方案可将其转换为字符序列,例如>用于_GT_以用于互操作目的) 。导致错误的直接原因是>在看到数字后立即发送到clojure.lang.LispReader/read,并且无法“退出”。


为了完整起见,进行切向讨论。

请注意,如果您手动构造符号,则可以使用它来命名Var:

readNumber

你甚至可以做像

这样的时髦的东西
;; 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{}

我认为如果一个人坚持做这类事情,最终会遇到JVM限制。这样做当然没有任何好处...无论如何,回到最初的问题,由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{} 引起的错误与符号文字语法有关,符号文字语法只对合理的程度是Java友好的。 “翻译”存在。具有名称的Clojure对象并不关心那些格式正确的名称或其他名称,尽管使用时髦的名称是笨拙的并且绝对不受支持。

(上面示例中的1+实际上是一个Java类 - 我有点惊讶地看到这个实际上有效,但另一方面我似乎记得JVM的内部限制名称应该不如Java那么严格。)