Predicate function for dotted pairs?

Q: is there a predicate function for dotted pairs?

In other words, is there a function that distinguishes between dotted pairs and 2-element proper lists:

(some-predicate-p '(a . b))             ; => t
(some-predicate-p '(a   b))             ; => nil

The broader context: I need to access the second element of a pair of values, and would like the function to "do the right thing" when it's fed either a dotted pair or a 2-element proper list:

(cdr  '(a . b))                           ; => b
(cadr '(a   b))                           ; => b

Since cdr and cadr cannot be dropped in interchangeably between proper and improper lists:

(cadr '(a . b))                           ; => error
(cdr  '(a   b))                           ; => (b)
• (and (cdr x) (atom (cdr x))) FWIW, this is a duplicate of this StackOverflow question, except that here you are testing only one cons.
– Drew
Apr 3 '15 at 17:08

Here is a simple test for a dotted pair (your question):

(and (cdr x) (atom (cdr x)))

And here is a test for a dotted list (of any length):

(let ((last  (last x))) (and (cdr last) (atom (cdr last))))

Got it: helped along by @abo-abo's answer, the following predicate function detects dotted pairs:

(defun dotted-p (x)
"Returns `t' if X is a dotted-pair."
(not (consp (cdr x))))

(dotted-p '(a . b))                     ; => t
(dotted-p '(a   b))                     ; => nil
• The only issue I could see here is that '(a . nil) be considered a dotted pair when really it just a 1 element proper list (equivilant to '(a)), If you wanted to account for this, and also for full type safety, you could use this is your function body (and (consp x) (cdr x) (not (consp (cdr x)))) Apr 3 '15 at 14:24
• @JordonBiondo: good point on the edge case. I think, for my specific use, I'd want to leave it as is, but the more general case should probably work as you're suggesting.
– Dan
Apr 3 '15 at 14:26
• I disagree. (cons a nil) is by definition a dotted pair, even though it can also be regarded as a one-element list. But I would certainly include the (consp x) condition as suggested by @JordonBiondo. Apr 10 '15 at 10:09

There isn't such a function to my knowledge, but you can use something like this:

(defun codr (x)
(let ((y (cdr x)))
(if (consp y)
(car y)
y)))

But it's better to just know what kind of data you're expecting.

• Thanks, although this function return the same value (b) when used on either a dotted-pair or a proper list: (codr '(a b)) => b and (codr '(a . b)) => b. Still, +1 because it pointed me in the right direction.
– Dan
Apr 3 '15 at 13:57
• And I agree that it's better to know the type of data to expect, but it's for end-user use and I'd like to allow people to use either version as their tastes dictate.
– Dan
Apr 3 '15 at 14:00