When I try this code on Emacs SLIME
, the apply
function gives a different result. Isn't it supposed to give the same result? Why does it give a different result? Thanks.
CL-USER> (apply #'(lambda (n)
(cons n '(b a))) '(c))
(C B A)
CL-USER> (cons '(c) '(b a))
((C) B A)
答案 0 :(得分:6)
cons
takes an element and a list as arguments. So (cons 'x '(a b c d))
will return (x a b c d)
.
apply
takes a function and a list of arguments -- but the arguments will not be passed to the function as a list! They will be split and passed individually:
(apply #'+ '(1 2 3))
6
(actually, it takes one function, several arguments, of which the last must be a list -- this list will be split and treated as "the rest of the arguments to the function". try, for example, (apply #'+ 5 1 '(1 2 3))
, which will return 12
)
Now to your code:
The last argument you passed to the apply
function is '(c)
, a list with one element, c
. Apply will treat it as a list of arguments, so the first argument you passed to your lambda
-form is c
.
In the second call, you passed '(c)
as first argument to cons
. This is a list, which was correctly included in the first place of the resulting list: ( (c) b a)
.
The second call would be equivalent to the first if you did
(cons 'c '(b a))
(c b a)
And the first call would be equivalent to the second if you did
(apply #'(lambda (n) (cons n '(b a))) '((c)))
((c) b a)
答案 1 :(得分:2)
CL-USER 51 > (cons '(c) '(b a))
((C) B A)
CL-USER 52 > (apply #'(lambda (n)
(cons n '(b a)))
'(c))
(C B A)
Let's use FUNCALL
:
CL-USER 53 > (funcall #'(lambda (n)
(cons n '(b a)))
'(c))
((C) B A)
See also what happens when we apply a two element list:
CL-USER 54 > (apply #'(lambda (n)
(cons n '(b a)))
'(c d))
Error: #<anonymous interpreted function 40600008E4> got 2 args, wanted 1.
答案 2 :(得分:2)
函数和apply
中的&amp; rest参数之间存在对称性。
(defun function-with-rest (arg1 &rest argn)
(list arg1 argn))
(function-with-rest 1) ; ==> (1 ())
(function-with-rest 1 2) ; ==> (1 (2))
(function-with-rest 1 2 3 4 5) ; ==> (1 (2 3 4 5))
想象一下,我们想要采用arg1
和argn
,并以与function-with-rest
相同的方式使用我们选择的函数以相同的方式使用它。我们将第一个参数加倍,然后对其余参数求和。
(defun double-first-and-sum (arg1 &rest argn)
(apply #'+ (* arg1 2) argn))
(double-first-and-sum 1 1) ; ==> 3
(double-first-and-sum 4 5 6 7) ; ==> 26
函数和&#34; rest&#34;之间的参数。参数是总是第一个的附加参数:
(apply #'+ 1 '(2 3 4)) ; ==> (+ 1 2 3 4)
(apply #'+ 1 2 3 '(4)) ; ==> (+ 1 2 3 4)
这非常方便,因为我们经常要添加的参数多于传递的参数(否则我们可能只是使用了apply
正在使用的函数。这里有一个名为zip
的东西:
(defun zip (&rest args)
(apply #'mapcar #'list args))
那么当你这样称呼时会发生什么:(zip '(a b c) '(1 2 3))
?好的args将是((a b c) (1 2 3))
,而apply
会使(mapcar #'list '(a b c) '(1 2 3))
成为((a 1) (b 2) (c 3))
,这将导致(apply #'(lambda (&rest n)
(cons n '(b a))) '(c))
;==> ((c) b a)
(apply #'(lambda (&rest n)
(cons n '(b a))) '(c d e))
;==> ((c d e) b a)
。你看到了对称吗?
因此,您可以在您的示例中完成此操作:
{{1}}