golconda
golconda

Reputation: 71

How to pass lexical bindings of functions to 'eval' in Emacs Lisp?

In Emacs Lisp, lexical environment are represented by an alist, mapping symbols to their value. It can be passed to evaluators as a second argument of 'eval' function.

(eval '(+ 3 var)
      '((var . 4)))
→ 7

However, I can't figure out how to pass functions, not variables, to the evaluator.

For example, either of the following expressions shows an error.

 (eval '(func 3)
       '((func . (lambda (x) (+ 4 x)))))
 → error: (void-function func)
 (eval '(func 3)
       '((func . (closure (t) (x) (+ 4 x)))))
 → error: (void-function func)

Any help is appreciated.

Upvotes: 2

Views: 349

Answers (2)

Stefan
Stefan

Reputation: 28531

Here's how you can do it:

(defun my-eval (exp var-bindings fun-bindings)
  (eval `(cl-flet ,(mapcar (lambda (x) (list (car x) `',(cdr x)))
                           fun-bindings)
           (let ,(mapcar (lambda (x) (list (car x) `',(cdr x)))
                         var-bindings)
             ,exp))
        t))

or, using eval's builtin support for var-bindings:

(defun my-eval (exp var-bindings fun-bindings)
  (eval `(cl-flet ,(mapcar (lambda (x) (list (car x) `',(cdr x)))
                           fun-bindings)
           ,exp)
        (or var-bindings t)))

[ BTW, note that it is not always true that in Emacs Lisp, lexical environment are represented by an alist: after byte-compilation, lexical variables don't have any name any more, they're stored on "the" stack and they're directly accessed via their position in the stack. ]

Upvotes: 1

V. Semeria
V. Semeria

Reputation: 3256

How about this :

(eval '(apply func (list 3))
       '((func . (lambda (x) (+ 4 x)))))

Upvotes: 1

Related Questions