Skip to content

LISP - some function

The some function is a powerful sequence predicate used to determine if at least one element in one or more sequences satisfies a given condition. It’s highly efficient because it stops processing and returns as soon as it finds a match.

(some predicate sequence &rest more-sequences)
  • predicate: A function that accepts as many arguments as there are sequences provided. It should return a non-nil value for a match, and nil otherwise.
  • sequence: The first sequence (list, vector, or string) to iterate over.

This is very important: some does not just return T (true). It returns the first non-nil value returned by the predicate. If the predicate never returns a non-nil value after checking all elements, some returns nil (false).

Let’s check if a list contains any even numbers.

(let ((list1 '(1 3 5 8 9))
(list2 '(1 3 5 7 9)))
;; The predicate `evenp` returns T for 8. `some` stops and returns T.
(print (some #'evenp list1)) ;=> T
;; No element satisfies `evenp`, so `some` returns NIL.
(print (some #'evenp list2)) ;=> NIL
)
T
NIL

Here, we’ll check a string for the first vowel. The predicate uses member, which returns the sublist starting at the found element—a non-nil value.

(defun find-first-vowel (s)
(some #'(lambda (char)
(member char '(#\a #\e #\i #\o #\u)))
s))
(let ((result1 (find-first-vowel "rhythm"))
(result2 (find-first-vowel "lisp-is-fun")))
;; No vowels, so the predicate always returns NIL.
(format t "Vowel found in 'rhythm': ~a~%" result1) ;=> NIL
;; The first vowel is 'i'. `member` returns `(#\i #\o #\u)`.
;; `some` stops and returns this list.
(format t "Vowel found in 'lisp-is-fun': ~a~%" result2) ;=> (#\I #\O #\U)
)
Vowel found in 'rhythm': NIL
Vowel found in 'lisp-is-fun': (#\I #\O #\U)

Example 3: Working with Multiple Sequences

Section titled “Example 3: Working with Multiple Sequences”

When you provide multiple sequences, the predicate receives one element from each sequence at each step. The iteration stops when the shortest sequence runs out.

;; Check if any element in list1 is greater than the corresponding element in list2
(let ((list-a '(1 5 3))
(list-b '(2 4 6)))
;; 1>2 is nil. 5>4 is T. `some` stops and returns T.
(print (some #'> list-a list-b)) ;=> T
)
(let ((list-c '(1 2 3))
(list-d '(4 5 6)))
;; All comparisons return nil, so the final result is NIL.
(print (some #'> list-c list-d)) ;=> NIL
)
T
NIL

some is perfect for expressing “exists” or “at least one” conditions concisely:

  • Validation: Check if any submitted data field contains invalid characters. (some #'invalid-char-p user-input)
  • Searching: Quickly determine if a list of products contains any items that are on sale. (some #'on-sale-p products)
  • State Checking: In a game, check if any enemy in a list is within attack range. (some #'in-range-p enemies)
Section titled “Related Predicates: every, notany, notevery”

some is part of a family of sequence predicates:

  • some: Is there at least one true result?
  • every: Are all results true?
  • notany: Are there no true results? (Is every result false?)
  • notevery: Is there at least one false result?