2009-03-19 23 views
10

ben lisp emacs'taki aşağıdaki yığın aşağıdaki SBCL kodelisp fonksiyonları

(defun avg-damp(f) 
    #'(lambda(x) (/ (+ (funcall f x) x) 2.0))) 

bir çağrı

(funcall (avg-damp #'(lambda(v) (* v v))) 10) 

döner 55.0 (doğru değeri), fakat çöker

Debugger entered--Lisp error: (void-variable f) 
    (funcall f x) 
    (+ (funcall f x) x) 
    (/ (+ (funcall f x) x) 2.0) 
    (lambda (x) (/ (+ ... x) 2.0))(10) 
    funcall((lambda (x) (/ (+ ... x) 2.0)) 10) 
    eval((funcall (avg-damp (function ...)) 10)) 
    eval-last-sexp-1(nil) 
    eval-last-sexp(nil) 
    call-interactively(eval-last-sexp) 

Emacs lisp'de nasıl çalışırım?

cevap

12

bir zor soru, ama nihayet got bu anladım. Sorun, avg-damp tanımında #''un, derleyicinin gerçek değerinin bilinmesinden önce, avara-rutubetinin derlendiği zaman, derleyicinin, lambda fonksiyonunu zamanında derlemesini sağlamasıdır.

(defun avg-damp (f) 
    `(lambda(x) (/ (+ (funcall ,f x) x) 2.0))) 

(funcall (avg-damp #'(lambda(v) (* v v))) 10) 

Backquoting hile yapar: ort-nemli böyle, çağrıldığında Sen zaman içinde daha sonraki noktaya Bu fonksiyonun derleme geciktirmek gerekir.

Düzenleme: Ne bu gibi bir uncurried formda ort-nemli tanımlarsanız Tabii ki, bütün sorun ortadan kalkana:

(defun avg-damp (f x) 
    (/ (+ (funcall f x) x) 2.0)) 

(funcall 'avg-damp #'(lambda(v) (* v v)) 10) 

Ama bunu yapmak için değil nedenleri var sanırım.

19

programlama Bu tarz düz Emacs Lisp çalışmaz. Emacs Lisp dinamik bağlamayı kullanır ve Şema ve Common Lisp gibi sözcükler sözcüksel bağlamayı kullanır. Kodunuz farkı ortaya çıkarır. Bkz .: Extent in Emacs Lisp

Ayrıca şu soruya da bakınız: How do I do closures in Emacs Lisp? ve lexical-let ile 'çözüm'. lexical-let, "cl" paketindeki Emacs Lisp için bir uzantıdır.

Ayrıca bakınız: Emacs 24.1 lexical binding opsiyonel olmadığı için. Nasıl kullanacağınızı öğrenin: using lexical binding.