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
?
'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.
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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With