Conditional Clojure Symbol Name Restrictions or Inherited?

In Common LISP, I can do:

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

In clojure, I can do the first (ignoring the fact that setf and def work differently)

 (def a1 'a) 

but with the second I get an error

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

Did clojure just inherit this restriction from Java, or is it intentional? (i.e. you cannot have a class name, a variable name, or a method name with Java with this style - so I assume it has just been ported.)

+4
source share
1 answer

Clojure character literals are documented to start with a non-numeric character. This has nothing to do with the Java identifier syntax or numeric literal - a Clojure character character is any clojure.lang.LispReader read method that reads as a character, and there are a number of characters allowed in Clojure characters that are not valid in Java identifiers (for example, - , > ...), as well as a scheme for translating them into sequences of characters, such as _GT_ for > for interaction purposes). The direct cause of the error is that clojure.lang.LispReader/read sent to readNumber immediately after viewing the digit and there is no way to " readNumber " from this.


Tangential discussion for completeness.

Note: if you build the character manually, you can use it to mean Var:

 ;; Clojure intern serves a different purpose to CL intern, see (doc intern) user> (intern *ns* (symbol "1+") inc) #'user/1+ user> ((ns-resolve *ns* (symbol "1+")) 1) 2 

You can even make funky ones, for example

 user> (eval `(defrecord ~(symbol "1foo") [])) user.1foo user> user.1foo user.1foo user> (user.1foo.) #:user.1foo{} 

... which, of course, is completely crazy, although perhaps not as much as

 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{} 

I believe that if someone insisted on doing such things, then in the end one might face the limitations of the JVM. Of course, there is no good purpose for this ... In any case, to the original question, the error caused by 1+ is related to the syntax of the character literal, which is Java-compatible only to the extent that a reasonable "translation" "exists. Clojure objects that have names do not really care that these names are well-formed or different, although the use of funky names is cumbersome and definitely not supported.

(And user.1foo from the above example is actually a Java class - I'm a little surprised to see that this really works, although on the other hand, I seem to remember that the internal restrictions of the JVM on names should be less strict than Java.)

+11
source

All Articles