zcohen
zcohen

Reputation: 317

Lisp - How can I check if a list is a dotted pair?

How can I check if a list in lisp is a dotted pair?

CL-USER 20 : 3 > (dotted-pair-p (cons 1 2))
T

CL-USER 20 : 3 > (dotted-pair-p '(1 2))
NIL

CL-USER 20 : 3 > (dotted-pair-p '(1 2 3))
NIL

I tried checking if length=2 but got error:

CL-USER 28 : 1 > (= (length (cons 2 3)) 2)
Error: In a call to LENGTH of (2 . 3), tail 3 is not a LIST.

Upvotes: 7

Views: 6372

Answers (5)

Student
Student

Reputation: 719

A dotted pair is a cons cell where it's CDR is not a cons itself (recursive definition). So this '(1 . 2) is a dotted pair, but this '(1 . ()) isn't, since it is just the printed representation of and the same as '(1).

(defun dotted-pair-p (x)
  (and (consp x)
       ;; Check that CDR is not a list with LISTP
       ;; since (CONSP ()) ;;=> NIL
       ;; and the CDR of a pair can't be NIL for it
       ;; to be dotted.
       (not (listp (cdr x)))))

(dotted-pair-p '(1 . 2))            ;T
(dotted-pair-p '(1 . ()))       ;NIL

Dotted lists (lists whose last cons cell is dotted) are defined in Common Lisp by LIST*. We can now use the above function to define a predicate for them too:

(defun list*p (x)
  (dotted-pair-p (last x))) 

(list*p (list* 1 2 3 4))        ;T
(list*p (list 1 2 3 4))         ;NIL

Upvotes: 0

Thibault Langlois
Thibault Langlois

Reputation: 99

You can check if a list is dotted (ends with a non-nil atom) with:

(defun dotted-listp (l)
  (cond ((null l) nil)
        ((atom l) t)
        (t (dotted-listp (cdr l)))))

Upvotes: -1

Diogo Franco
Diogo Franco

Reputation: 486

Because a list always ends with the empty list, while a pair doesn't:

(listp (cdr '(1 2))) => T
(listp (cdr '(1 . 2))) => NIL

Upvotes: 3

Efi G
Efi G

Reputation: 997

(not(listp(cdr (cons 1 2))))=> T
(not(listp(cdr (list 1 2))))=> nill

Upvotes: 0

nixeagle
nixeagle

Reputation: 1002

A lisp list in "dotted pair notation" looks something like:

(1 . ()).

Since this is homework, I'll let you take this to the logical conclusion. Compare

(LIST 1 2) => (1 . (2 . ()))

with

(CONS 1 2) => (1 . 2).

What is different between these two? How can you tell the difference using predicates?

Remember all proper lisp lists end with the empty list. Ask yourself how do you access the second element of a cons pair? The solution from there ought to be clear.

Upvotes: 8

Related Questions