Search code examples
emacselisp

How to pass operators in expressions in elisp?


I am reading Root of Lisp, and come across this example:

(
 (lambda (f) (f '(b c)))
 '(lambda (x) (cons 'a x)))

However, if I evaluated it in Emacs, I got

Symbol's function definition is void: f

If I try it on https://repl.it/languages/scheme, where it uses Schema as the lisp interpreter, I got

Error: ('lambda ('x) ('cons ('quote 'a) 'x)) is not a function [(anon), (anon)]

If I remove the quote on the 2nd lambda expression, this example works on repl.it, but still got the same error on Emacs.


Solution

  • Applying the function f to '(b c) must be done using funcall. So the following works:

    (
     (lambda (f) (funcall f '(b c)))
     '(lambda (x) (cons 'a x)))
    

    and evaluates to (a b c).

    Paul Graham is probably using some variant of lisp with only one namespace for function names and data variables (Lisp-1 or Scheme model) in his article whereas Elisp is a Lisp-2 language with different namespaces for functions/variables. This allows to have the same name for a function and a variable.

    So for something like

    (some-function some arguments)
    

    the elisp executor only searches some-function in the function namespace which makes a construct like funcall or apply necessary when you want to call a function associated with a variable from the variable namespace.

    The separate function/variable namespace in elisp may lead to unexpected behavior if not understood:

    (defun do-something () (1))
    (setq do-something #'(lambda () (2)))
    
    (do-something) ;; => 1
    (funcall do-something) ;; => 2