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