9

I see sharp quotes being used in other people's eLisp code, and I use them myself, but I'm not completely clear on when they are appropriate and when not.

Could anyone clarify on exactly when it's appropriate to use sharp quotes and when ordinary single quotes should be used instead?

11

#' is just shorthand for function, just as ' is shorthand for quote.

You can use it anywhere where you want to indicate to the byte-compiler or the interpreter or a human reader that its argument is expected to be (is treated as) a function.

In many contexts the context determines how the argument is treated if, for example, you simply quote it (use quote or ') instead of using #' (or function). For example, in a context where a symbol is used only for its symbol-function property, i.e., it is used as a function, you can just pass the symbol (e.g. by quoting it or passing a variable whose value is the symbol).

But sometimes code is clearer if you do use #' in such contexts. Even if Emacs-Lisp itself understands that the symbol is used as a function in such contexts, it might help to emphasize this for a human reader of the code.

In some other Lisps, the treatment of lambda forms that are simply quoted (with ') or are unquoted can differ from their use in a function position when quoted using function (#'). But not in Emacs Lisp. In Emacs Lisp you need not quote (using either ' or #') a lambda form that you want treated as a function (and not simply as a list). If you do want it handled as just a list, with car lambda etc., then quote it (with ') -- the example below illustrates this.

From (elisp) Anonymous Functions:

-- Special Form: function function-object

This special form returns FUNCTION-OBJECT without evaluating it.

In this, it is similar to quote (*note Quoting::). But unlike quote, it also serves as a note to the Emacs evaluator and byte-compiler that FUNCTION-OBJECT is intended to be used as a function. Assuming FUNCTION-OBJECT is a valid lambda expression, this has two effects:

• When the code is byte-compiled, FUNCTION-OBJECT is compiled into a byte-code function object (*note Byte Compilation::).

• When lexical binding is enabled, FUNCTION-OBJECT is converted into a closure. *Note Closures::.

The read syntax #' is a short-hand for using function. The following forms are all equivalent:

(lambda (x) (* x x))
(function (lambda (x) (* x x)))
#'(lambda (x) (* x x))

In the following example, we define a change-property function that takes a function as its third argument, followed by a double-property function that makes use of change-property by passing it an anonymous function:

(defun change-property (symbol prop function)
   (let ((value (get symbol prop)))
     (put symbol prop (funcall function value))))

(defun double-property (symbol prop)
   (change-property symbol prop (lambda (x) (* 2 x))))

Note that we do not quote the lambda form.

If you compile the above code, the anonymous function is also compiled. This would not happen if, say, you had constructed the anonymous function by quoting it as a list:

(defun double-property (symbol prop)
   (change-property symbol prop '(lambda (x) (* 2 x))))

In that case, the anonymous function is kept as a lambda expression in the compiled code. The byte-compiler cannot assume this list is a function, even though it looks like one, since it does not know that change-property intends to use it as a function.

9

#' (aka function) can be used in front of (lambda ...) but it's redundant there, so the only place where it's really meaningful is in front of a symbol, as in #'car. In ELisp, #'car and 'car are almost completely equivalent, so one of the main purpose is simply to document the intention (i.e. to indicate to whoever reads this code that you intend to use this symbol as a function). Yet there are a few circumstances, where the difference is more significant:

  • The byte-compiler takes advantage of this documented intention and when you write #'car it will check whether car exists as a function, and if it doesn't find it, it will emit a warning, just like it would if you had a call to that function.
  • Inside cl-flet and cl-labels, only #'f can refer to the locally defined function f, because 'f will still refer to the global symbol f (and whichever function might be stored in its symbol-function slot). E.g.

    (cl-flet ((car (x y) (+ x y)))
      (list #'car 'car))
    =>
    ((closure nil (x y) (+ x y)) car)
    

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.