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只计算一次。现在这是完整答案。谢谢Elispcl循环
也支持这种语法。
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