2009-07-28 1 views
33

을 LISP는 표준 배합 호출 할 경우 나도 몰라,하지만 난 '렛트'를 사용하는 GNU 설명서에 의해 권고하고 로컬 함수 바인딩 : 그러나하자 이맥스에서 렛트는

(defun adder-with-flet (x) 
    (flet ((f (x) (+ x 3))) 
    (f x)) 
) 

을 우연히 나는 let '을 사용하여 변수에 람다 표현식을 묶는 다음 표현식을 Scheme에서 재생 한 후 시도했다. mapcar에 함수를 전달하면 작동한다. * :

(defun adder-with-let (x) 
    (let ((f (lambda (x) (+ x 3)))) 
    (car (mapcar* f (list x)))) 
) 

두 기능 모두 작동 :

(adder-with-flet 3) ==> 6 
(adder-with-let 3) ==> 6 

두 번째 이유는 무엇입니까? 'let'을 사용하여 함수를 심볼에 바인딩하는 데 사용할 수있는 설명서를 찾을 수 없습니다.

+0

이 시도는, flet'가있는 경우에는 '('CL을 요구하려고하면 사용중인 이맥스 버전에서 사용하지 못할 수 있습니다 '주의)'('flet'은 CommonLisp입니다.). – Robert

+0

어떤 GNU 매뉴얼은 여기서'flet'을 사용할 것을 권장합니까? – Stefan

+1

이멕스 25.1.1 설명 기능 : flet이 매크로는 24.3 이후 폐기되었습니다. 'cl-flet '또는'cl-letf'를 사용하십시오. – AAAfarmclub

답변

37

Scheme과 달리 Emacs Lisp는 2-lisp입니다. 즉, 각 기호에는 값 바인딩과 함수 바인딩이라는 두 가지 별도의 바인딩이 있습니다. 함수 호출 (a b c d)에서 함수 바인딩을 사용하여 첫 번째 심볼 (a)을 조회하고 값 바인딩을 사용하여 나머지 (b c d)를 조회합니다. 특수 서식 let은 새 (로컬) 값 바인딩을 만들고 flet은 새 함수 바인딩을 만듭니다. 가치 함수 또는 룩업 사용 바인딩 여부 것을

참고하지 입력 보면서 촬영 값에서 (a b c d) 함수 호출에 위치에 의존한다. 특히 값 바인딩은 함수로 해석 될 수 있습니다.첫 번째 예에서

, 당신은 (flet를 통해) f - 바인딩 기능을 다음 함수 조회 할 : 두 번째 예에서

(f ...) 

을, 당신 (let를 통해) 함수에 값을 바인드 f 값 조회를 사용하십시오.

(... f ...) 

두 경우 모두 같은 종류의 바인딩 및 조회를 사용하기 때문에 둘 다 작동합니다.

http://en.wikipedia.org/wiki/Common_Lisp#Comparison_with_other_Lisps

+0

설명 주셔서 감사합니다! 필자는 value-lookup과 function-lookup을 구분한다. 필자는 함수와 변수에 대해 별도의 네임 스페이스를 사용하는 것에 익숙했지만 mapcar *에서 변수로 바인딩 된 함수를 호출하는 방법과 연결할 수 없었습니다. – hatmatrix

18

나는 Emacs lisp 매뉴얼을 빠르게 찾았으며 'flet에 대한 참조를 찾을 수 없었습니다. - common-lisp package의 일부이기 때문에별로 놀랍지 않습니다.

let도 로컬 바인딩을 수행하지만 그 심볼의 "function cell"에는 바인딩되지 않습니다. 이 예

작동 :

(let ((myf (lambda (x) (list x x)))) 
    (eval (list myf 3))) 

하지만

(let ((myf (lambda (x) (list x x)))) 
    (myf 3)) 

을 오류와 함께 실패합니다 : "리스프 오류 : (무효 기능 myf)"반면에

flet, 않습니다 함수 셀에 대한 바인딩을 수행하면됩니다.

(flet ((myf (x) (list x x))) 
    (myf 3)) 

차이점이 flet 인 경우 let이 아닌 반면 myf 기호를 직접 사용할 수 있다는 점에 유의하십시오. "값 셀"에서 함수를 가져 와서 적절하게 적용하려면 간접적 인 방법을 사용해야합니다.

예에서 'mapcar'은 내 용도가 'eval 인 것과 같습니다.

+0

답장을 보내 주셔서 감사합니다! zielaj의 설명과 함께 나는이 '평가'가 어떻게 작동 하는지를 봅니다. 예, flet은 cl 확장자로 나타납니다. 나는 원래 flet을 사용하기 전에 'cl'이 필요하다는 것을 읽었지 만 더 새로운 이맥에서 이것은 더 이상 그렇지 않다는 것을 알았습니다 ... – hatmatrix

+5

'cl' 확장자가 Emacs와 함께 출하되기 전에, 어떻게 사람들이 let-like 의미 체계로 선언 될 필요가있는 함수 정의를 처리합니까? eval이 그것을 할 수있는 방법이라고 받아 들였습니까? – d11wtq

7

는 d11wq @ 이러한 목적을 위해`funcall '이있다. 다음은 작동합니다 :

(defun adder-with-let (x) 
    (let ((f #'(lambda (x) (+ x 3)))) 
    (funcall f 3))) 

(adder-with-let 3) ;=> 6 
0

원치 않는 경우 flet을 사용할 필요가 없습니다. 다음 예에서와 같이 let을 사용하여 정의 된 지역 기호의 기능 셀에 함수를 배치 : 8을 반환이 평가

(let ((ALocalSymbol)) 
    (fset 'ALocalSymbol (lambda (x) (* 2 x))) 
    (ALocalSymbol 4) 
) 

(let ((ALocalSymbol))...)ALocalSymbol 앞의 견적을 알 마십시오. setq 기호는 따옴표이지만 fset은 그렇지 않습니다.

flet은 통사론의 종류입니다. 평범한 구 let을 사용하여 무의미한 기호를 정의하면 설정할 심볼의 "셀"을 선택할 수 있습니다. setq을 사용하여 기호의 값 셀을 설정하거나 fset을 사용하여 함수 셀을 설정할 수 있습니다. 이 도움이

희망, 사람에게

파블로

+0

이것은 완전히 틀린 것이며, 인턴 된 심볼 인'ALocalSymbol'에 대한 (단일) 전역 함수 셀을 바인딩합니다. (* value * 셀만 let-bound입니다.) interned 심볼의 let-binding (값) 대신 * new * (uninterned) 심볼을 생성하는 경우이 작업을 수행 할 수 있습니다. – phils

+0

명확성을 위해 :이 코드는 전역 함수 네임 스페이스에서 함수 'ALocalSymbol'을 정의합니다. 그 이름의 함수가 이미 정의 되었다면, 그 함수는 clobbered입니다. – phils

+0

uninterned 심볼을 생성했다면'(ALocalSymbol 4)'는 여전히 interned 심볼의 함수를 호출 할 것이므로 uninterned 심볼/함수를'funcall' (또는 유사한)해야 할 필요가 있음을주의하십시오. – phils