在lisp中应用和关键字参数

pro*_*eek 1 lisp keyword apply

我可以在LISP中使用关键字参数

(member 'a '(a b c) :test #'eq)
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试使用apply来调用成员方法时

(apply #'member 'a '(a b c) :test #'eq)
Run Code Online (Sandbox Code Playgroud)

我有如下错误信息:

MEMBER: keyword arguments in (:TEST) should occur pairwise
 [Condition of type SYSTEM::SIMPLE-PROGRAM-ERROR]
Run Code Online (Sandbox Code Playgroud)

解决方案是

(apply #'member 'a '(a b c) '(:test eq))
Run Code Online (Sandbox Code Playgroud)

而没有关键字参数

(apply #'member 'a '((a b c)))
Run Code Online (Sandbox Code Playgroud)

这背后的逻辑是什么?为什么'(:test#'eq)会引发错误?

添加

这就是我问这个问题的原因.我有来自ANSI Common Lispbook第103页的代码.

(defun our-adjoin (obj lst &rest args)
       (if (apply #'member obj lst args)
           lst
           (cons obj lst)))
Run Code Online (Sandbox Code Playgroud)

当我尝试(our-adjoin 'a '(a b c))它时返回结果(A B C),但是my-adjoin不能被翻译为(apply #'member 'a '(a b c)),因为它会引发错误(如在lisp中的Apply和关键字参数中所要求的那样).

我能想到的是,&rest args给出的值是为了做出(apply #member 'a '(a b c) '())不会引起错误的东西.

mic*_*ica 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
Run Code Online (Sandbox Code Playgroud)

我不知道什么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)
Run Code Online (Sandbox Code Playgroud)

编辑: (apply #'member 'a '(a b c))

这是一样的

(member 'a 'a 'b 'c)
Run Code Online (Sandbox Code Playgroud)

这当然是胡说八道.想想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)) ...)
Run Code Online (Sandbox Code Playgroud)

所以你的假设(相当于(apply #'member 'a '(a b c) '()))是正确的.(仅供参考,有没有什么区别nil,'nil,(),'(),和(list).)