I am reading through a book for homework, and I understand that using #' is treating the variable as a function instead of a variable. But I am a little hazy on FUNCALL. I understand that lisp makes object out of variables, so is the function name just a 'pointer' (may be a bad word, but hopefully you get what I mean), in which case you use #' to invoke it, or is funcall the only way to invoke them? ex.
(defun plot (fn min max step)
(loop for i from min to max by step do
(loop repeat (funcall fn i) do (format t "*"))
(format t "~%")))
couldn't I just do:
(defun plot (fn min max step)
(loop for i from min to max by step do
(loop repeat #'(fn i) do (format t "*"))
(format t "~%")))
I guess my confusion lies in what exactly is in the function names. When I read the book, it said that the variable's value is what will be the function object.
funcall applies function to args. If function is a symbol, it is coerced to a function as if by finding its functional value in the global environment.
In Common Lisp apply is a function that applies a function to a list of arguments (note here that "+" is a variadic function that takes any number of arguments): (apply #'+ (list 1 2)) Similarly in Scheme: (apply + (list 1 2))
#'function-name
is (function function-name)
. Nothing is called, evaluating either results in the function associated with function-name
(the object representing the function). funcall
is used to call functions.
See funcall and function in the HyperSpec.
Sample session using both:
CL-USER> (defun square (x) (* x x))
SQUARE
CL-USER> #'square
#<FUNCTION SQUARE>
CL-USER> (function square)
#<FUNCTION SQUARE>
CL-USER> (funcall #'square 3)
9
CL-USER> (funcall 'square 3)
9
The second invocation of funcall
works because it also accepts a symbol as function designator (see the link for funcall
above for details).
The #'
and funcall
notations are needed in Common Lisp because this language is a so-called "Lisp-2" where a given symbol can have two separate and unrelated main "meanings" normally listed as
These are approximate explanations, as you will see in the following example that "first element of a form" and "any other place" are not correct definitions.
Consider for example:
the above code prints 144
... it may seem surprising at first but the reason is that the same name square
is used with two different meanings: the function that given an argument returns the result of multiplying the argument by itself and the local variable square with value 12.
The first and third uses of the name square
the meaning is the function named square
and I've painted the name with red color. The second and fourth uses instead are about a variable named square
and are painted in blue instead.
How can Common Lisp decide which is which? the point is the position... after defun
it's clearly in this case a function name, like it's a function name in the first part of (square square)
. Likewise as first element of a list inside a let
form it's clearly a variable name and it's also a variable name in the second part of (square square)
.
This looks pretty psychotic... doesn't it? Well there is indeed some splitting in the Lisp community about if this dual meaning is going to make things simpler or more complex and it's one of the main differences between Common Lisp and Scheme.
Without getting into the details I'll just say that this apparently crazy choice has been made to make Lisp macros more useful, providing enough hygiene to make them working nicely without the added complexity and the removed expressiveness power of full hygienic macros. For sure it's a complication that makes it harder to explain the language to whoever is learning it (and that's why Scheme is considered a better (simpler) language for teaching) but many expert lispers think that it's a good choice that makes the Lisp language a better tool for real problems.
Also in human languages the context plays an important role anyway and there it's not a serious problem for humans that sometimes the very same word can be used with different meanings (e.g. as a noun or as a verb like "California is the state I live in" or "State your opinion").
Even in a Lisp-2 you need however to use functions as values, for example passing them as parameters or storing them into a data structure, or you need to use values as functions, for example calling a function that has been received as parameter (your plot case) or that has been stored somewhere. This is where #'
and funcall
come into play...
#'foo
is indeed just a shortcut for (function foo)
, exactly like 'x
is a shortcut for (quote x)
. This "function" thing is a special form that given a name (foo
in this case) returns the associated function as a value, that you can store in variables or pass around:
(defvar *fn* #'square)
in the above code for example the variable *fn*
is going to receive the function defined before. A function value can be manipulated as any other value like a string or a number.
funcall
is the opposite, allowing to call a function not using its name but by using a value...
(print (funcall *fn* 12))
the above code will display 144... because the function that was stored in the variable *fn*
now is being called passing 12 as argument.
If you know the "C" programming language an analogy is considering (let ((p #'square))...)
like taking the address of the function square
(as with { int (*p)(int) = □ ...}
) and instead (funcall p 12)
is like calling a function using a pointer (as with (*p)(12)
that "C" allows to be abbreviated to p(12)
).
The admittely confusing part in Common Lisp is that you can have both a function named square
and a variable named square
in the same scope and the variable will not hide the function. funcall
and function
are two tools you can use when you need to use the value of a variable as a function or when you want a function as a value, respectively.
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