是否有任何标准函数通过应用单值来迭代谓词?

gav*_*koa 2 common-lisp higher-order-functions

总有一些跨值,如列表迭代许多功能mapcar,every,some.

我需要跨谓词迭代单值:

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

(let ( (val (complex-expr ...)) )
   (and (pred1 val) (pred2 val) ... (predN val)))
Run Code Online (Sandbox Code Playgroud)

是否有任何标准函数使用语法执行上述代码:

(some-p val pred1 pred2 ... predN)
(every-p val pred1 pred2 ... predN)
Run Code Online (Sandbox Code Playgroud)

更新 FYI Elisp在其标准库中具有此功能:

run-hook-with-args-until-success
run-hook-with-args-until-failure
run-hook-with-args
Run Code Online (Sandbox Code Playgroud)

Jos*_*lor 8

标准不包括任何与你所要求的完全相同的东西,但它确实包括一些每一个用于计算(或(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
Run Code Online (Sandbox Code Playgroud)

你想要做的事情适合这个范例,除了你需要的f应该取每个x i,把它当作一个函数,并用一些值来调用它. 一些每一个仍然在这里工作:

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
Run Code Online (Sandbox Code Playgroud)

当然,你可以在函数中包含另一个函数以避免每次都编写lambda函数:

(defun some-p (value predicates)
  (some (lambda (predicate)
          (funcall predicate value))
        predicates))
Run Code Online (Sandbox Code Playgroud)

CL-USER> (some-p "hello" '(characterp numberp))
NIL
CL-USER> (some-p 3 '(characterp numberp))
T
Run Code Online (Sandbox Code Playgroud)

如果你真的希望函数具有可变参数(就像你在问题中所展示的那样),你可以使用&rest参数来完成它,但要注意这些函数大多使用的风格不是:

(defun some-p (value &rest predicates)
  (some (lambda (predicate)
          (funcall predicate value))
        predicates))
Run Code Online (Sandbox Code Playgroud)

CL-USER> (some-p 3 'characterp 'numberp)
T
CL-USER> (some-p "hello" 'characterp 'numberp)
NIL
Run Code Online (Sandbox Code Playgroud)

但是,将参数作为列表更为常见.两个很好的理由(这是同一现象的一部分)是:(i)从另一个来源传递列表更容易.例如,[a][b]更容易做到:

(let ((preds '(p1 p2 ... pn)))
  (some-p-list value preds)           ; [a]
  (apply 'some-p-rest value preds))   ; [b]
Run Code Online (Sandbox Code Playgroud)

即使你不介意适用[B] ,如赖Joswig注意到 在评论中,有一个恒定的呼叫参数限制在一个Common Lisp实现,它限制对参数的函数可以调用的数量.它通常很大,但它可以小到50.这意味着如果preds有50个元素,那么(应用'some-p-rest值preds)就会失败.

  • @gavenkoa我猜,它经常不被提及*,但我敢打赌,你真的很熟悉它.毕竟,你知道你会做`(mapcar(lambda(x)(*x 2))'(1 2 3 4 5 6))`而不是`(mapcar(lambda(x)(*x 2) )1 2 3 4 5 6)`.这不是一个严格的规则,但是如果你有一个谓词列表从其他地方进来并且你使用**和rest**参数,你必须做**apply**; 例如,`(let((ps'(p1 p2 p3)))(应用'some-p value ps))`.如果将列表作为单个参数,则可以执行`(let((ps'(p1 p2 p3)))(some-p value ps))`. (2认同)