在lisp中应用和关键字参数

时间:2013-04-29 01:22:18

标签: lisp keyword apply

我可以在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)会引发错误?

ADDED

这就是我问这个问题的原因。 我有来自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) '())之类的东西不会引发错误。

2 个答案:

答案 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视为“扩展”其最后一个论点。

编辑2: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*
  • 第一个参数是函数

  • 然后是几个参数,至少有一个,其中最后一个参数需要是一个列表