我可以在LISP中使用关键字参数
(member 'a '(a b c) :test #'eq)
但是,当我尝试使用apply来调用成员方法
时(apply #'member 'a '(a b c) :test #'eq)
我的错误信息如下:
MEMBER: keyword arguments in (:TEST) should occur pairwise
[Condition of type SYSTEM::SIMPLE-PROGRAM-ERROR]
解决方案是
(apply #'member 'a '(a b c) '(:test eq))
而没有关键字参数
(apply #'member 'a '((a b c)))
这背后的逻辑是什么?为什么'(:test#'eq)会引发错误?
这就是我问这个问题的原因。 我有来自ANSI Common Lispbook第103页的代码。
(defun our-adjoin (obj lst &rest args)
(if (apply #'member obj lst args)
lst
(cons obj lst)))
当我尝试(our-adjoin 'a '(a b c))
时,它返回结果(A B C)
,但我们的邻居无法翻译为(apply #'member 'a '(a b c))
,因为它会引发错误(如{}中所述{3}})。
我能想到的是&rest args
的值是为了使(apply #member 'a '(a b c) '())
之类的东西不会引发错误。
答案 0 :(得分:5)
apply
期望其最终参数为列表。也就是说,
(apply #'foo (list 1 2 3)) == (foo 1 2 3)
(apply #'member 'a '(a b c) :test #'eq) == ??? ; is an error - #'eq isn't a list
我不知道apply
对#'eq
(一个函数)的预期列表是什么,但这就是问题。
您可能正在寻找funcall
而不是apply
:
(funcall #'foo 1 2 3) == (foo 1 2 3)
(funcall #'member 'a '(a b c) :test #'eq) == (member 'a '(a b c) :test #'eq)
(apply #'member 'a '(a b c))
这与
相同(member 'a 'a 'b 'c)
当然是胡说八道。将apply
视为“扩展”其最后一个论点。
our-adjoin
代码(our-adjoin 'a '(a b c) :test #'eq)
;; is equivalent to
(if (apply #'member 'a '(a b c) (list :test #'eq))
lst
(cons obj lst))
;; is equivalent to
(if (member 'a '(a b c) :test #'eq) ...)
(our-adjoin 'a '(a b c))
;; is equivalent to
(if (apply #'member 'a '(a b c) (list)) ...) ; (list) == nil
;; is equivalent to
(if (member 'a '(a b c)) ...)
所以你的假设(相当于(apply #'member 'a '(a b c) '())
)是正确的。 (仅供参考,nil
,'nil
,()
,'()
和(list)
之间没有区别。)
答案 1 :(得分:4)
APPLY,以便我们可以使用计算参数列表调用函数。
APPLY
具有以下语法:
apply function &rest args+ => result*
第一个参数是函数
然后是几个参数,至少有一个,其中最后一个参数需要是一个列表