Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between seq and sequence in Clojure?

Those following examples are producing same output.

(seq [1 2 3 4])
=> (1 2 3 4)

(sequence [1 2 3 4])
=> (1 2 3 4)
like image 433
Ertuğrul Çetin Avatar asked Aug 10 '16 14:08

Ertuğrul Çetin


People also ask

What does seq do in Clojure?

A seq is a logical list, and unlike most Lisps where the list is represented by a concrete, 2-slot structure, Clojure uses the ISeq interface to allow many data structures to provide access to their elements as sequences. The seq function yields an implementation of ISeq appropriate to the collection.

What makes a sequence different from a list?

A list is a sequence but a sequence is not necessarily a list. A sequence is any type that supports the sequence interface ("protocol"). Sequence types describe a functional superset.

Is a sequence a collection?

"Collection" and "Sequence" are abstractions, not a property that can be determined from a given value. Collections are bags of values. Sequence is a data structure (subset of collection) that is expected to be accessed in a sequential (linear) manner.

What is a lazy sequence in Clojure?

Overview. Clojure is not a lazy language. However, Clojure supports lazily evaluated sequences. This means that sequence elements are not available ahead of time and produced as the result of a computation.


2 Answers

The difference is that sequence always returns a seq even if the collection is empty (in that case an empty list), while seq returns nil for empty collections. Also, sequence can be used with transducers.

A look into the source code:

user=> (source sequence)
(defn sequence
  "Coerces coll to a (possibly empty) sequence, if it is not already
  one. Will not force a lazy seq. (sequence nil) yields (), ..."
  ([coll]
     (if (seq? coll) coll
         (or (seq coll) ())))
  ...

So calling sequence with only a collection calls seq on the collection if it isn't already a seq and returns an empty list if the collection was nil.

like image 189
Michiel Borkent Avatar answered Sep 25 '22 11:09

Michiel Borkent


first of all, they treat empty sequence argument differently:

user> (seq nil)
nil
user> (seq ())
nil
user> (sequence ())
()
user> (sequence nil)
()

also sequence has additional arities to operate on transducers

as of docs:

clojure.core/sequence

[coll]

[xform coll]

[xform coll & colls]

Added in 1.0 Coerces coll to a (possibly empty) sequence, if it is not already one. Will not force a lazy seq. (sequence nil) yields (), When a transducer is supplied, returns a lazy sequence of applications of the transform to the items in coll(s), i.e. to the set of first items of each coll, followed by the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. The transform should accept number-of-colls arguments

clojure.core/seq

[coll]

Added in 1.0 Returns a seq on the collection. If the collection is empty, returns nil. (seq nil) returns nil. seq also works on Strings, native Java arrays (of reference types) and any objects that implement Iterable. Note that seqs cache values, thus seq should not be used on any Iterable whose iterator repeatedly returns the same mutable object.

like image 27
leetwinski Avatar answered Sep 26 '22 11:09

leetwinski