6

I'm learning Lisp from the book 'Practical Common Lisp'. At one point, I'm supposed to enter the following bit of code:

[1] (remove-if-not #'evenp '(1 2 3 4 5 6 7 8 9 10))
(2 4 6 8 10)

I suppose the idea here is of course that remove-if-not wants a function that can return either T or NIL when an argument is provided to it, and this function is then applied to all symbols in the list, returning a list containing only those symbols where it returned NIL.

However, if I now write the following code in CLISP:

[2] (remove-if-not 'evenp '(1 2 3 4 5 6 7 8 9 10)
(2 4 6 8 10)

It still works! So my question is, does it even matter whether I use sharp-quote notation, or is just using the quote sufficient? It now seems like the additional sharp is only there to let the programmer know that "Hey, this is a function, not just some random symbol!" - but if it has any other use, I'd love to know about it.

I use GNU CLISP 2.49 (2010-07-07, sheesh that's actually pretty old).

Anonymous
  • 431
  • 3
  • 9

3 Answers3

14

Sharp-quote and quote do not have the same behaviour in the general case:

(defun test () 'red)

(flet ((test () 'green))
  (list (funcall 'test)
        (funcall #'test))) => (red green)

Calling a quoted symbol will use the function value of the quoted symbol (ie, the result of symbol-function). Calling a sharp-quoted symbol will use the value established by the lexical binding, if any, of the symbol. In the admittedly common case that there is no lexical binding the behaviour will be the same. That's what you are seeing.

You should get into the habit of using sharp-quote. Ignoring function bindings is probably not what you want, and may be confusing to anybody trying to understand your code.

gsg
  • 9,167
  • 1
  • 21
  • 23
  • There are cases where you want the function's name and not the function, e.g. `(defvar *some-fn* 'my-fn)`. Now, you can redefine `my-fn` without changing the variable, as you would if you had used `#'my-fn`. – acelent Jan 30 '14 at 17:01
  • Calling a function through the symbol is not confusing to anyone who is actually a Lisp programmer. It is useful when you want to refer to the global function binding of a symbol even if there is a lexical one, vaguely like, say, `::foo()` in C++. It also ensures late binding: the binding is resolved when the call is evaluated. Whereas `#'func` can compile in such a way that the call still goes to the previous definition of `func` when `func` is subsequently redefined (when the caller and callee are in the same file). – Kaz Dec 15 '16 at 15:22
5

This is not CLISP specific, it works in every Common Lisp implementation (I use Clozure Common Lisp here).

What happens is that if you give a symbol as a function designator then the implementation will look up the symbol-function (assuming the symbol is available in the global environment) for you:

? #'evenp
#<Compiled-function EVENP #x3000000F2D4F>
? (symbol-function 'evenp)
#<Compiled-function EVENP #x3000000F2D4F>

In general you can use either, but there's an interesting effect if you rebind the called function later. If you specify the function (#' or (function)) then the calls will still call the old function because the lookup has been done at compile time; if you use the symbol then you will call the new function because the lookup is re-done at runtime. Note that this may be implementation-specific.

uselpa
  • 18,732
  • 2
  • 34
  • 52
  • have you actually tried what you say? Take CLISP... Using the function quote can also pick up the changed function. – Rainer Joswig Jan 28 '14 at 16:31
  • 1
    It might be worth noting that `#'(lambda ...)` and `(lambda ...)` work but `'(lambda ...)` will not. – Samuel Edwin Ward Jan 28 '14 at 16:42
  • @RainerJoswig Yes I did, but not in CLISP. This might be implementation-specific, but it's nevertheless useful to know. – uselpa Jan 28 '14 at 17:27
  • If you use a file compile it might be the case. But in interactive computation using the interpreter and the incremental compiler Lisp usually picks up the current definition. – Rainer Joswig Jan 28 '14 at 20:40
0

As you have noticed (or read) funcall et. al. are will make an effort to convert the function argument you provide into something approprate. So as you have noticed they will take a symbol and then fetch the symbol-function of that symbol; if that works out they will then invoke that.

Recall that #'X is converted at readtime into (symbol-function x) and 'x into (quote x). It's good practice to have the symbol-function work done at compile time.

But why? Well two trival reasons it is slightly faster and it signals that you don't intend to redefine F's symbol-function after compile time. Another reason is that in a recent Pew Research study 98.3% of Lisp developers prefer it, and 62.3% will shun those that don't do this.

But there's more.

'(lambda (..) ...) is quite different v.s. #'(lambda (..) ...). The first is very likely to end up using eval, i.e. it will be slow. The first runs in a different scope v.s. the second one, i.e. only the second one can see the lexical scope it appears in.

Ben Hyde
  • 1,503
  • 12
  • 14
  • The last paragraph is a bit misleading and detracts from the answer. The syntax `(lambda ...)` itself not a function designator in Common Lisp. `(funcall '(lambda ...) ...)` is erroneous. It can be done, but like this `(funcall (coerce '(lambda () 42) 'function))`. – Kaz Dec 15 '16 at 15:29