Skip to main content

complement

complement Function

Syntax:

complement function → complement-function

Arguments and Values:

function—a function.

complement-function—a function.

Description:

Returns a function that takes the same arguments as function, and has the same side-effect behavior as function, but returns only a single value: a generalized boolean with the opposite truth value of that which would be returned as the primary value of function. That is, when the function would have returned true as its primary value the complement-function returns false, and when the function would have returned false as its primary value the complement-function returns true.

Examples:

(funcall (complement #’zerop) 1) → true 
(funcall (complement #’characterp) #\A) → false
(funcall (complement #’member) ’a ’(a b c)) → false
(funcall (complement #’member) ’d ’(a b c)) → true

See Also:

not

Notes:

(complement x) #’(lambda (&rest arguments) (not (apply x arguments)))

In Common Lisp, functions with names like “xxx-if-not” are related to functions with names like “xxx-if” in that

(xxx-if-not f . arguments) (xxx-if (complement f) . arguments)

For example,

(find-if-not #’zerop ’(0 0 3))

(find-if (complement #’zerop) ’(0 0 3)) → 3

Data and Control

Note that since the “xxx-if-not” functions and the :test-not arguments have been deprecated, uses of “xxx-if” functions or :test arguments with complement are preferred.

Expanded Reference: complement

Basic usage: negating a predicate

complement takes a function and returns a new function that returns the logical opposite of the original.

(funcall (complement #'zerop) 1) → T
(funcall (complement #'zerop) 0) → NIL

Filtering with complemented predicates

complement is commonly used with higher-order functions like remove-if and find-if to avoid the deprecated -if-not variants.

;; Find the first non-alphabetic character
(find-if (complement #'alpha-char-p) "hello world!")
=> #\Space

;; Remove non-numeric elements (equivalent to remove-if-not)
(remove-if (complement #'numberp) '(1 a 2 b 3 c))
=> (1 2 3)

Replacing -if-not functions

The -if-not family of functions is deprecated. Use the corresponding -if function with complement instead.

;; Instead of (find-if-not #'zerop '(0 0 3)):
(find-if (complement #'zerop) '(0 0 3))
=> 3

;; Instead of (remove-if-not #'evenp '(1 2 3 4 5)):
(remove-if (complement #'evenp) '(1 2 3 4 5))
=> (2 4)

Works with multi-argument predicates

complement preserves the arity of the original function.

(funcall (complement #'<) 3 5) → NIL
(funcall (complement #'<) 5 3) → T

(funcall (complement #'string-equal) "foo" "FOO") → NIL

Using complement with member

complement only looks at the primary return value of the original function.

(funcall (complement #'member) 'a '(a b c)) → NIL
(funcall (complement #'member) 'd '(a b c)) → T