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) '())不会引起错误的东西.
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"扩大"它的最后一个论点.
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).)