2

An any function would evaluate a function (or predicate) on elements of a sequence, returning true if the predicate returns true for any element of the sequence. Therefore

(any `stringp `(42 t "yes" nil))

..would return non-nil, and

(any `stringp `(42 t nil 89))

...would return nil.

I think there is a some function in the CL module, but I don't want to use that.

It's easy to write a naive implementation using mapc:

(defun my-any (predicate sequence)
  "Return true if PREDICATE is true of any element of SEQUENCE.
If so, return the first non-nil value returned by PREDICATE.
"
  (let (result)
    (mapc '(lambda (elt)
             (or result
                 (setq result (funcall predicate elt))))
          sequence)
    result))

But can anyone provide optimizations or improvements on this? Is there a faster or cleaner or more idiomatic elisp way to do this? In particular what is the best way to stop mapping through the sequence when the first one fires? I could "unroll" mapc, but is that the best way?

I think I could use a catch but that may actually cost more than it saves.

tips?

4

3 回答 3

5
(defun any (pred list)
  (while (and list (not (funcall pred (car list))))
    (pop list))
  (car list))
于 2012-04-06T22:10:46.303 回答
2

至少,当谓词为真时,您可以提前终止。像下面的东西。

 (defun my-any (predicate sequence)
  "Return true if PREDICATE is true of any element of SEQUENCE.
If so, return the first non-nil value returned by PREDICATE.
"
  (catch 'looking
    (mapc '(lambda (elt)
             (if (funcall predicate elt) (throw 'looking t)))
          sequence)
    nil))
于 2012-04-06T21:30:02.063 回答
1

您可能可以使用find-if,描述于http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node145.html

听起来它正是你想要的

(find-if 'stringp '(a "yes"))
"yes"
(find-if 'stringp '(a b))
nil
于 2012-04-06T19:47:24.907 回答