代码之家  ›  专栏  ›  技术社区  ›  hawkeye

故意的clojure符号名限制或继承?

  •  4
  • hawkeye  · 技术社区  · 14 年前

    在普通的Lisp中,我可以做到:

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

    在Clojure中,我可以先做(忽略了setf和def工作方式不同的事实)

    (def a1 'a)
    

    但第二次我出错了

    (def 1a 'b)
    
    java.lang.NumberFormatException: Invalid number: 1a
    

    Culjule是否只是从Java中继承了这个限制,或者是故意的?(用这个样式,Java不能有类名、变量或方法名,所以我假设它只是跨接的。)

    1 回复  |  直到 11 年前
        1
  •  11
  •   Michał Marczyk    14 年前

    Clojure符号文字 are documented 需要以非数字字符开头。这与Java标识符或数字文字语法无关——Culjule符号文字是任意的。 clojure.lang.LispReader read 方法以符号的形式读取,并且在Java标识符中不允许的Culjule符号文字中允许有许多字符(例如)。 - , > …;还有一个将这些转换成字符序列的方案,例如 _GT_ 对于 > 用于互操作)。错误的直接原因是 clojure.lang.LispReader/read 派遣到 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{}
    

    …当然,这是完全疯狂的,尽管可能不如

    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+ 与符号文字语法有关,它只对一个合理的“翻译”的程度是友好的。有名字的Clojure对象不太关心那些名字的格式是否正确,尽管使用时髦的名字很难,而且绝对不受支持。

    (和) user.1foo 从上面的例子来看,实际上是一个Java类——我很惊讶地看到这一个实际上已经工作了,虽然另一方面,我似乎记得JVM对名字的内部限制应该比Java的严格限制。