【问题标题】:Deliberate Clojure symbol name limitations or inherited?刻意的 Clojure 符号名称限制或继承?
【发布时间】:2010-08-02 09:09:13
【问题描述】:

在 Common 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 有一个类名、变量或方法名——所以我假设它只是被继承了。)

【问题讨论】:

  • 请注意,在 Common Lisp 中,符合规范的实现可能会将 1a 解析为一个数字,就像 Clojure 尝试的那样(即使没有将 *read-base* 设置为大于 10 的值)。请参阅 HyperSpec 中有关潜在数字的条目:lispworks.com/documentation/HyperSpec/Body/02_caa.htm

标签: java clojure jvm


【解决方案1】:

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 严格。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-08
    • 1970-01-01
    相关资源
    最近更新 更多