Common lisp 是否有任何标准函数可以通过应用于单个值来迭代谓词?

Common lisp 是否有任何标准函数可以通过应用于单个值来迭代谓词?,common-lisp,higher-order-functions,Common Lisp,Higher Order Functions,总是有许多函数用于在值列表中进行迭代,如mapcar,每一个,一些 我需要针对单个值跨谓词进行迭代: (let ( (val (complex-expr ...)) ) (or (pred1 val) (pred2 val) ... (predN val))) (let ( (val (complex-expr ...)) ) (and (pred1 val) (pred2 val) ... (predN val))) 是否有任何标准函数使用语法执行上述代码: (some-p v

总是有许多函数用于在值列表中进行迭代,如
mapcar
每一个
一些

我需要针对单个值跨谓词进行迭代:

(let ( (val (complex-expr ...)) )
   (or (pred1 val) (pred2 val) ... (predN val)))

(let ( (val (complex-expr ...)) )
   (and (pred1 val) (pred2 val) ... (predN val)))
是否有任何标准函数使用语法执行上述代码:

(some-p val pred1 pred2 ... predN)
(every-p val pred1 pred2 ... predN)
更新供参考:


该标准没有包括任何与您要求的完全相同的内容,但它确实包括用于计算(或(f x1)(f x2)…(f xn))(和(f x1)(f x2)…(f xn))的部分和

CL-USER> (some 'evenp '(1 2 3 4 5))
T
CL-USER> (every 'evenp '(1 2 3 4 5))
NIL
(let ((preds '(p1 p2 ... pn)))
  (some-p-list value preds)           ; [a]
  (apply 'some-p-rest value preds))   ; [b]
您试图做的符合这个范例,除了您需要的f应该取每个xi,将其视为一个函数,并用一些值调用它有些和每个
仍然在这里工作:

CL-USER> (let ((value 3))
           (some (lambda (predicate) (funcall predicate value)) '(evenp symbolp oddp)))
T
CL-USER> (let ((value "hello"))
           (some (lambda (predicate) (funcall predicate value)) '(characterp numberp)))
NIL
当然,您可以将其包装到另一个in函数中,以避免每次都写入lambda函数:

(defun some-p (value predicates)
  (some (lambda (predicate)
          (funcall predicate value))
        predicates))

如果您真的希望函数可变(如您在问题中所示),可以使用&rest参数执行,但请注意,这不是大多数此类函数使用的样式:

(defun some-p (value &rest predicates)
  (some (lambda (predicate)
          (funcall predicate value))
        predicates))

不过,将参数作为列表更为常见。这有两个很好的原因(这是同一现象的一部分)是:(i)从另一个来源传递列表更容易。例如,做[a]比做[b]更容易:

CL-USER> (some 'evenp '(1 2 3 4 5))
T
CL-USER> (every 'evenp '(1 2 3 4 5))
NIL
(let ((preds '(p1 p2 ... pn)))
  (some-p-list value preds)           ; [a]
  (apply 'some-p-rest value preds))   ; [b]

即使您不介意[b]中的应用,因为在通用Lisp实现中有一个常量调用参数限制,它限制了函数可以调用的参数数量。它通常很大,但可以小到50。这意味着如果preds有50个元素,那么(应用'some-p-rest-value preds)将失败。

没有标准函数,但很容易编写:

请注意,您也可以使用
循环
宏:

一些

CL-USER 10 > (loop with value = 4
                   for pred in (list #'numberp #'plusp #'oddp)
                   thereis (funcall pred value))
T

CL-USER 11 > (loop with value = 3
                   for pred in (list #'numberp #'plusp #'oddp)
                   always (funcall pred value))
T
every-p

CL-USER 16 > (defun every-p (value predicates)
               (loop for predicate in predicates
                     always (funcall predicate value)))
EVERY-P

CL-USER 17 > (every-p 3 (list #'numberp #'plusp #'oddp))
T

我不知道用列表代替变量的传统,谢谢你的回答+1@gavenkoa我想这不常被提及,但我敢打赌你确实很熟悉它。毕竟,你知道你会做
(mapcar(lambda(x)(*x2))”(123456))
,而不是
(mapcar(lambda(x)(*x2))123456)
。这不是一个硬性的规则,但是如果你有来自其他地方的谓词列表,并且你使用&rest参数,你就必须应用它;e、 例如,
(让((ps)(p1p2p3))(应用“some-p值ps))
。如果将列表作为单个参数,则可以执行
(let((ps)(p1 p2 p3))(some-p value ps))
。ABCL的CALL-ARGUMENTS-LIMIT=50。LispWorks=2047。参数列表的长度有限。请参阅变量CALL-ARGUMENTS-LIMIT,它必须为50(!)或更大。这意味着,在某些实现中,它可能只有50个。因此,如果使用列表,则将它们作为参数传递,而不使用参数列表。有一个目标是消除
let
绑定,使复杂的表达式只计算一次。这可以通过宏或函数调用完成,也可以是其他方法。@gavenkoa在(值为complex expr…)的循环中,complex expr只计算一次。现在这是完整答案。谢谢Elisp
cl循环
也支持这种语法。
CL-USER 16 > (defun every-p (value predicates)
               (loop for predicate in predicates
                     always (funcall predicate value)))
EVERY-P

CL-USER 17 > (every-p 3 (list #'numberp #'plusp #'oddp))
T