tags:

views:

263

answers:

4

I am learning the concept of sequence and nil in Clojure. This was the result of a small experimentation.

1:6 user=> (first '())
nil
1:7 user=> (rest '())
()
1:8 user=> (first (rest '()))
nil

Does this mean that '() is actually a sequence of nils?

A: 

Also learning Clojure.

For empty sequences, rest returns a sequence for which seq returns nil.

That's why you get that behavior.

I assume this is to simplify recursing on sequences until they are empty, and probably other smartypants reasons...

Dan Fitch
+2  A: 

first and rest are functions that apply to a logical structure (a seq) and not on the linked cons structure of a list (as in other lisps).

Clojure defines many algorithms in terms of sequences (seqs). 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.

http://clojure.org/sequences

The behavior is a result of the definition of the function and not determined by the primitive structure of the data.

Pinochle
A: 

Technically yes though not in a useful way.

"Does the sequence that is created by calling (seq '()) have an infinite number of nulls?"
the answer is yes becase the (rest) of an empty sequence is sill an empty sequence which it's self can have a (rest)

This output is misleading by the way:

1:7 user=> (rest '())
()

the first '() in this is the empty list.
the secong () in this is the empty sequence.
sequences are printed the same as lists in the repl even though they are not the same.

Arthur Ulfeldt
+3  A: 

If you want to test whether the "rest" of a collection is empty, use next.

user> (next '(foo bar))
(bar)
user> (next '())
nil
user> (doc next)
-------------------------
clojure.core/next
([coll])
  Returns a seq of the items after the first. Calls seq on its
  argument.  If there are no more items, returns nil.

"nil-punning" (treating an empty collection/seq and nil as the same thing) was removed last year in favor of fully-lazy sequences. See here for a discussion leading up to this change.

Brian Carper
When I write cond clauses to recur in a sequence, my first check is usually (empty? obj). Is that the correct way to recur in Clojure?
kunjaan
I think usually people test (seq obj) rather than `(empty? obj)`.
Brian Carper