Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between FUNCALL and #'function-name in common lisp?

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.

like image 773
Andy Avatar asked Mar 08 '12 05:03

Andy


People also ask

What does Funcall do in Lisp?

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.

What is apply in Lisp?

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))


2 Answers

#'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).

like image 119
Miron Brezuleanu Avatar answered Nov 15 '22 14:11

Miron Brezuleanu


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

  1. When used as first element of a form it means a function
  2. When used in any other place it means a variable

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:

lisp-2

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) = &square; ...}) 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.

like image 35
6502 Avatar answered Nov 15 '22 12:11

6502