Search code examples
clojure

Is seq from PersistentVector faster than seq from PersistentList when we pushed elements to the end?


Is seq from PersistentVector

(seq [1 2 3])

faster than seq from PersistentList

(seq '(1 2 3))

when we pushed elements into them? Are their performance equal except type?

I tried to find answer in the internet but unfortunately didn't find any about comparison of

(seq [1 2 3])

and

(seq `(1 2 3))

Solution

  • The type of [1 2 3] is PersistentVector and the type of (1 2 3) is clojure.lang.Cons.

    Calling seq just calls to RT.seq, which has a shortcut if the collection is an instance of ASeq, otherwise calls to RT.seqFrom to create a new sequence. Since Cons is already an instance of ASeq, it will just return the argument without creating a new seq object.

    user=> (def abc `(1 2 3))
    #'user/abc
    
    user=> (identical? abc (seq abc))
    true
    

    To summarize, calling (seq '(1 2 3)) should be slightly faster than calling (seq [1 2 3]), because in the former case, it just returns the argument directly, but in the latter case, a new ChunkedSeq is allocated for the vector.

    However, please note that the difference might be still negligible in production environments and there are many other factors to consider when writing code for really low latency applications.