2016-12-12 1 views
2

In Emacs Lisp wird die lexikalische Umgebung durch einen Alist repräsentiert, der Symbole auf ihren Wert abbildet. Es kann als zweites Argument der 'eval'-Funktion an Evaluatoren übergeben werden.Wie lexikalische Bindungen von Funktionen an 'eval' in Emacs Lisp übergeben?

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

Allerdings kann ich nicht herausfinden, wie Funktionen übergeben, nicht Variablen, den Bewerter.

Zum Beispiel zeigt einer der folgenden Ausdrücke einen Fehler an.

(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) 

Jede Hilfe wird geschätzt.

+0

Emacs Lisp ist ein [Lisp-2] (https://en.wikipedia.org/wiki/LISP_2), kein [Lisp-1] (https://en.wikipedia.org/wiki/LISP_1)). – Drew

Antwort

1

Wie wäre es damit:

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

Es tut mir leid, das wird die Funktion beschränken nur einmal angewendet werden und die erste., Und das ist nicht das, was ich wollte. Wie wäre es, sagen wir, der Ausdruck ist so etwas wie: ‚(+ (func (func (func 3))) 4) ? – golconda

+0

Nein, es gibt keine solche Beschränkung: Sie können '(+ (funcall func (funcall func (funcall func 3)))) 4)'. – Stefan

1

Hier ist, wie Sie es tun können:

(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)) 

oder unter Verwendung von eval ‚s eingebaute Unterstützung für 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, Beachten Sie, dass es nicht immer wahr ist, dass in Emacs Lisp die lexikalische Umgebung durch dargestellt wird ein Alist: Nach der Byte-Kompilierung haben lexikalische Variablen keinen Namen mehr, sie werden auf "dem" Stapel gespeichert und sie werden direkt über ihre Position im Stapel erreicht. ]

+0

Danke! Darf ich die Frage weiter stellen? (Ich habe einmal über die Verwendung von cl-flet/cl-label nachgedacht, konnte aber das folgende Problem nicht lösen.) Wie wäre es mit der Funktion mit Closures, deren Symbole die Werte von äußeren lexikalischen Scope-Bindungen enthalten? Zum Beispiel, was ich wirklich wollte, war so etwas wie (let ((4)) (eval ‚(func 3) ' ((Func. (Verschluss ((b., A) t) (x) (+ xb)))))) als '7' zu bewerten. – golconda

+0

Sie sollten '(closure ...)' nicht in Ihren Code schreiben, da dies ein Wert ist, den Sie zur Laufzeit erstellen möchten. IOW anstelle von ''((func. (Closure ((b., A) t) (x) (+ xb))))' schreiben '\' ((func., (Lambda (x) (+ xb)))) '. – Stefan