Символьные литералы Clojure задокументированы , чтобы начинать с нецифрового символа. Это не имеет ничего общего с идентификатором Java или числовым литеральным синтаксисом - литерал символа Clojure - это любой метод clojure.lang.LispReader
read
, считываемый как символ, и в литералах символа 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.)