emacselisp

How to use `apply-partially`?


I'm trying to use apply-partially in a local context:

((apply-partially '+ 1) `(1))

This give me the following error: eval: Invalid function: (apply-partially (quote +) 1)

similarly:

(let ((addone (apply-partially #'+ 1)))
  (addone 2))

Why any of this example doesn't work?


Solution

  • That's because Emacs Lisp has separate namespaces for variables and functions. A function that has been defined using defun can be called by putting its name first in a list and evaluating that, but if you have a function as a value (as returned by apply-partially) you need to use funcall or apply.

    The difference between funcall and apply is that funcall just calls the function with the arguments given, while apply treats its last argument as a list that should be appended to the argument list. Thus, your first example needs to be written with apply, since + doesn't work with lists:

    (apply (apply-partially '+ 1) `(1))
    

    For your second example, use funcall, since the function argument is not wrapped in a list:

    (let ((addone (apply-partially #'+ 1)))
      (funcall addone 2))
    

    This is sometimes referred to as "Lisp-1" vs "Lisp-2". "Lisp-1" languages such as Scheme and Clojure have one namespace for variables and functions, while "Lisp-2" languages such as Emacs Lisp and Common Lisp have separate namespaces. See also:

    The way it works in Emacs Lisp is that each symbol has multiple "cells", one for its value as a variable and one for its function definition. So the function cell of the symbol list contains the built-in function, while you're free to put whatever value you want in its value cell. (This doesn't apply to lexical variables, which are stored in a "lexical environment" instead of in value cells of symbols.)

    In fact, each symbol has a third cell holding its property list. You can access individual properties of a symbol using the get and put functions, and you can get the entire properly list by calling symbol-plist. So you could say that Emacs Lisp has more than 2 namespaces, despite it being called a "Lisp-2" language.