any
函数将评估序列元素的函数(或谓词),如果谓词对序列的任何元素返回true,则返回true。因此
(any `stringp `(42 t "yes" nil))
..将返回非零,
(any `stringp `(42 t nil 89))
...将返回零。
我认为CL模块中有some
函数,但我不想使用它。
使用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))
但是,任何人都可以提供优化或改进吗?是否有更快或更清洁或更惯用的elisp方式来做到这一点?特别是当第一个序列触发时,停止映射序列的最佳方法是什么?我可以“展开”mapc,但这是最好的方法吗?
我想我可以使用catch
,但实际上可能会花费更多费用。
提示?
答案 0 :(得分:5)
(defun any (pred list)
(while (and list (not (funcall pred (car list))))
(pop list))
(car list))
答案 1 :(得分: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))
答案 2 :(得分:1)
您可以使用http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node145.html
中描述的find-if
听起来它完全符合您的要求
(find-if 'stringp '(a "yes"))
"yes"
(find-if 'stringp '(a b))
nil