LISP : consp or listp ?

December 19, 2014

I recently began my long-awaited journey(or a pilgrimage to be honest!) towards the wonderful ‘land’ of LISP. And along the path, I started understanding the so-called predicates.1

I also began to learn about the predicates that are built-in, such as oddp, evenp, atomp, etc.

Then, I stumbled across what seemed like 2 different predicates that are ‘equivalent’, but which I realized are not exactly so.

So, I want to discuss briefly about the subtle difference between these 2 predicates viz., consp & listp in LISP.

Beginning LISPers are bound to be a bit confused by the existence of the predicates consp & listp. One seems to check if its argument is a cons-cell (Please see the Notes section at the bottom for more info or intro to cons-cell ) while the other tells if the argument represents a list. After all, isn’t every list a cons-cell? Or so, the thought process goes…leading one to believe (erroneously!) that these predicates are interchangeable.

Isn’t every list a cons-cell?

Seems so, but it is not the case.

So, are consp & listp not the same?

Short answer : They are not the same. There’s a subtle difference due to one chief exception.

Note that NIL is a list, also denoted by (). But it is not a cons-cell.

There! I’m done!

I hope you ‘got’ the subtle difference between consp & listp predicates in LISP.

It should now be clear what the following code snippets produce:


(consp NIL)

Output: NIL

where as,


(listp NIL)

Output: T


Q & A


What is a cons-cell?

A cons-cell, in Java-parlance, is like the node struct/class of a linked-list. Like so,

class Node<T> {
    T data;
    Node next;
}

Note that the data field above is also a pointer/reference to some location in memory, just like next points to the ‘next’ node of the list. Thus a cons-cell is essentially a pair of pointers used to represent lists in LISP. In a singly-linked-list the last node has next set to null.

LISP uses this cons-cell concept to represent lists. For more information on cons-cells, you can refer to this introductory article. Enjoy!


If a predicate always returns Yes/No or True/False why does the output here show T & NIL ?

Good observation! You will understand this when you learn the basics of LISP.


Update: Thanks to Jean-Philippe Paradis of HexstreamSoft for pointing out another observation worth sharing–that NIL sometimes exhibits cons-like behaviour too, in that both (car NIL) and (cdr NIL) return NIL just like it would if you had used (car ()) and (cdr ()). Try it out!


Footnotes


  1. Predicates (in LISP) are nothing but functions that answer Yes/No type of questions. By convention LISP predicate-names end in the letter p (stands for ‘predicate’!) ↩︎

comments powered by Disqus