2009-03-19 2 views
10

나는이 혀짤배기 이맥스에 다음 스택 다음과 SBCL 코드elisp 기능

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

호출

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

반환 55.0 (정확한 값)하지만 충돌

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에서 작동하게 할 수 있습니까?

답변

12

까다로운 질문이지만 마침내 알아 냈습니다. 문제는 avg-damp의 정의에있는 #'은 컴파일러가 f의 실제 값이 알려지기 전에 에서 avg-damp 자체가 컴파일 될 때을 컴파일 할 때 람다 함수를 컴파일하게 만듭니다.

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

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

Backquoting 트릭을 수행합니다 평균-습기가이 같은를 호출 할 때 당신은 시간에 나중에에 를이 함수의 컴파일을 지연해야합니다.

편집 : 당신은이와 같은 uncurried 형태로 평균-젖은 정의하는 경우 물론, 모든 문제가 사라집니다 :

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

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

하지만 난 당신이 그렇게 할 아닌 이유가있을 것 같아요.

19

이 프로그래밍 방식은 일반 Emacs Lisp에서는 작동하지 않습니다. Emacs Lisp는 동적 바인딩을 사용하며 Scheme 및 Common Lisp와 같은 언어는 어휘 바인딩을 사용합니다. 코드가 차이를 나타냅니다. 참조 : Extent in Emacs Lisp

이 질문도 참조하십시오 : How do I do closures in Emacs Lisp? 및 '해결책'(어휘 추출). lexical-let은 "cl"패키지의 Emacs Lisp 확장입니다.

다음을 참조하십시오 : Emacs 24.1 이후에는 선택 사항 인 lexical binding이 있습니다. 그것을 사용하는 방법을 배우십시오 : using lexical binding.