(no = (escriba `(1)) (escriba` (1 2))) ;; ¿Por qué? (lista de un solo elemento, sintaxis-comillas, Contras, PersistentList)

I see this behavior in Clojure 1.2.1:

user=> (type '(1 2))
clojure.lang.PersistentList
user=> (type `(1 2)) ;; notice syntax-quote
clojure.lang.Cons
user=> (type '(1))
clojure.lang.PersistentList
user=> (type `(1))
clojure.lang.PersistentList

I expected `(1) to be a Cons just like `(1 2) is.

También probé:

user=> (type (cons 1 nil)) 
clojure.lang.PersistentList
user=> (type (cons 1 `()))
clojure.lang.Cons
user=> (type (cons 1 '()))
clojure.lang.Cons
user=> (type (cons 1 []))
clojure.lang.Cons

So what is the reason for `(1) and (cons 1 nil) to be PersistentLists?

preguntado el 09 de marzo de 12 a las 15:03

2 Respuestas

Like amalloy says, you shouldn't program against those exact types but against the seq abstracción.

However, I think I can take a guess at the reason. The Clojure forms that produce a PersistentList finalmente llamar RT.java, específicamente el cons(Object x, Object coll) method. It begins with a pretty odd check: if(coll == null) return new PersistentList(x), after which it creates a Cons object if that check doesn't pass. If you look at earlier versions of the code, puedes encontrar esto:

static public IPersistentCollection cons(Object x, IPersistentCollection y) {
    if(y == null)
        return new PersistentList(x);
    return y.cons(x);
}

So in an earlier version of the function, the call was dispatched to the cons method of the second argument, so the case when the second argument was null (es decir nil in Clojure) needed special handling. Later versions don't do that dispatching (or actually do it but in a different way, presumably to support a larger variety of collection types), but the check has been retained since it does not break any correctly written code.

respondido 09 mar '12, 17:03

Thanks for the answer! That explains the behavior. I thought there's a good reason for things to work this way, but if I understand correctly this is just a quirk, right? - Łukasz Kożuchowski

I think so. If you really want to find out, try removing that check and see if anything breaks. - Jouni K. Seppänen

If you care about the difference, your program is incorrect. They're both seqs, in the sense that (seq? x) returns true; the rest is implementation details you shouldn't depend on.

respondido 09 mar '12, 16:03

I don't need it for any program :) I just hope to learn something about Clojure. - Łukasz Kożuchowski

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.