Skip to main content

rassoc, rassoc-if, rassoc-if-not

rassoc, rassoc-if, rassoc-if-not Function

Syntax:

rassoc item alist &key key test test-not → entry

rassoc-if predicate alist &key key → entry

rassoc-if-not predicate alist &key key → entry

Arguments and Values:

item—an object.

alist—an association list.

predicate—a designator for a function of one argument that returns a generalized boolean. test—a designator for a function of two arguments that returns a generalized boolean. test-not—a designator for a function of two arguments that returns a generalized boolean. key—a designator for a function of one argument, or nil.

entry—a cons that is an element of the alist, or nil.

Description:

rassoc, rassoc-if, and rassoc-if-not return the first cons whose cdr satisfies the test. If no such cons is found, nil is returned.

If nil appears in alist in place of a pair, it is ignored.

Examples:

(setq alist ’((1 . "one") (2 . "two") (3 . 3)))
→ ((1 . "one") (2 . "two") (3 . 3))
(rassoc 3 alist) → (3 . 3)
(rassoc "two" alist) → NIL
(rassoc "two" alist :test ’equal) → (2 . "two")
(rassoc 1 alist :key #’(lambda (x) (if (numberp x) (/ x 3)))) → (3 . 3)
(rassoc ’a ’((a . b) (b . c) (c . a) (z . a))) → (C . A)
(rassoc-if #’stringp alist) → (1 . "one")
(rassoc-if-not #’vectorp alist) → (3 . 3)

See Also:

assoc, Section 3.6 (Traversal Rules and Side Effects)

Notes:

The :test-not parameter is deprecated.

The function rassoc-if-not is deprecated.

It is possible to rplaca the result of rassoc, provided that it is not nil, in order to “update” alist. The expressions

(rassoc item list :test fn)

and

(find item list :test fn :key #’cdr)

are equivalent in meaning, except when the item is nil and nil appears in place of a pair in the alist. See the function assoc.

Expanded Reference: rassoc, rassoc-if, rassoc-if-not​

Reverse association list lookup​

rassoc searches an alist by matching against the cdr (value) of each pair, rather than the car (key). It returns the entire pair, or NIL if not found.

(rassoc 2 '((a . 1) (b . 2) (c . 3)))
=> (B . 2)

(rassoc 99 '((a . 1) (b . 2) (c . 3)))
=> NIL

Finding a key by its value​

rassoc is the reverse of assoc: use car on the result to get the key associated with a value.

(car (rassoc 'green '((apple . green) (banana . yellow) (cherry . red))))
=> APPLE

String values require a :test argument​

Like assoc, the default test is eql, which does not work for string comparison.

(rassoc "two" '((2 . "two") (3 . "three")) :test #'equal)
=> (2 . "two")

(rassoc "two" '((2 . "two") (3 . "three")))
=> NIL

rassoc-if: search by predicate on the value​

rassoc-if applies a predicate to the cdr of each pair.

(rassoc-if #'stringp '((1 . 100) (2 . "hello") (3 . "world")))
=> (2 . "hello")

(rassoc-if #'zerop '((a . 5) (b . 0) (c . 3)))
=> (B . 0)

Using :key for custom extraction​

The :key function is applied to the cdr of each pair before testing.

(rassoc 3 '((a . (1 2 3)) (b . (4 5 6))) :key #'length)
=> (A 1 2 3)

Practical use: reverse lookup in a bidirectional mapping​

rassoc enables reverse lookups in an alist used as a bidirectional map.

(let ((codes '((:us . "United States")
(:uk . "United Kingdom")
(:fr . "France"))))
;; Forward lookup
(cdr (assoc :uk codes))
;; Reverse lookup
(car (rassoc "France" codes :test #'equal)))
=> :FR