David S.
David S.

Reputation: 11200

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.

Upvotes: 1

Views: 219

Answers (1)

Simon Fromme
Simon Fromme

Reputation: 3174

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

Upvotes: 4

Related Questions