Search code examples
clojuresequencecons

Why Clojure coerces string to character with cons


I played around with sequences in REPL and encountered the following behavior which, atleast to me, is pretty unintuitive. So I evaluated expression (cons '("1" "2") "3") expecting it to yield (("1" "2") "3") but instead it yielded (("1" "2") \3).

Could someone explain why Clojure automatically coerces string to character in this case? I'd assume this has something to do with the internal representation of the string as sequence of characters.


Solution

  • The second argument to cons is a sequence:

    (cons x seq)

    Returns a new seq where x is the first element and seq is the rest.

    Now you should know that clojure creates a sequence automatically for you if you don't give it one. For instance, calling seq (which cons does for you) would show you that the string is transformed into a character sequence:

    (seq "32")
    => (\3 \2)
    

    This is done by clojure's runtime in RT.java:

    else if(coll instanceof CharSequence)
        return StringSeq.create((CharSequence) coll);
    

    Instead if you want the character to be treated like a single item then you can wrap it:

    (cons '("1" "2") '("3"))
    => (("1" "2") "3")