问题
It seems both
(mapcar 'car '((foo bar) (foo1 bar1)))
and
(mapcar #'car '((foo bar) (foo1 bar1)))
work as the same.
And I also know '
means (quote symbol) and #'
means (function function-name).
But what's the underlying difference? Why these 2 both work in previous mapcar
?
回答1:
'foo
evaluates to the symbol FOO.
#'foo
evaluates to the function bound to the name FOO.
In Lisp a symbol can be called as a function when the symbol FOO has a function binding. Here CAR is a symbol that has a function binding.
But this does not work:
(flet ((foo (a) (+ a 42)))
(mapcar 'foo '(1 2 3 4 5)))
That's because FOO as a symbol does not access the local lexical function and the Lisp system will complain when foo
is not a function defined elsewhere.
We need to write:
(flet ((foo (a) (+ a 42)))
(mapcar #'foo '(1 2 3 4 5)))
Here the (function foo) or its shorthand notation #'foo refers to the lexical local function FOO.
Note also that in
(funcall #'foo ...)
vs.
(funcall 'foo ...)
The later might do one more indirection, since it needs to lookup the function from the symbol, while #'foo denotes the function directly.
Summary:
If a symbol has a function binding, calling a function through the symbol works.
回答2:
Why these 2 both work in previous mapcar?
The documentation for mapcar says:
If function is a symbol, it is coerced to a function as if by symbol-function.
回答3:
Try passing an anonymous function (lambda) to your mapcar
and you'll see that #'
is required since the quote by itself expects a symbol that is bound to a function, but the symbol doesn't exist in an un-named function:
CL-USER> (mapcar '(lambda (x) (format t "it is ~d" x)) (list 3 5 7))
; Evaluation aborted on #<TYPE-ERROR expected-type: (OR FUNCTION SYMBOL)
datum: (LAMBDA (X) (FORMAT T "it is ~d" X))>.
vs:
CL-USER> (mapcar #'(lambda (x) (format t "it is ~d" x)) (list 3 5 7))
it is 3it is 5it is 7
(NIL NIL NIL)
来源:https://stackoverflow.com/questions/4906255/whats-the-difference-between-and-in-lisp