2013-10-17 3 views
6

이 함수 빌더는 P.Graham의 "ANSI Common Lisp"(110 페이지)에서 컴포지션을 구현합니다. 인수는 n> 0 인용 된 함수 이름입니다. 나는 완전히 이해하지 못하는, 그래서 그 아래 내 질문을 여기에 코드를 인용하고 지정할 수 있습니다 :(compose) in Common Lisp

(defun compose (&rest fns) 
    (destructuring-bind (fn1 . rest) (reverse fns) 
    #'(lambda (&rest args) 
     (reduce #'(lambda (v f) (funcall f v)) 
       rest 
       :initial-value (apply fn1 args))))) 

구성하는 인수 목록은 반전과 (지금 첫번째) 요소을 Fn1 '에 바인딩, 압축 해제된다 '나머지는'쉬다 '. 가장 바깥 쪽의 람다 본문은 reduce : (funcall fi (funcall fi-1 ...))이며 피연산자는 역순으로 복원되어 초기 값으로 복원됩니다.

1) 가장 바깥 쪽 람다 식의 역할은 무엇입니까? 즉, 'args'는 어디에서 가져 옵니까? destructuring-bind의 첫 번째 인수로 지정된 데이터 구조입니까? 2) 가장 안쪽의 람다는 두 개의 인수를 어디에서 가져 옵니까?

나는 코드가하는 일을 이해할 수 있지만 어휘 범위는 나에게 약간의 수수께끼이다. 앞으로 모든 의견을 기다리십시오! 미리 감사드립니다. // Marco

+0

가 될 수 있을까? – Marcin

+1

사과드립니다.이 문제에 대한 토론은 http://stackoverflow.com/questions/5928106/compose-example-in-paul-grahams-ansi-common-lisp – ocramz

+0

@Marcin에서 눈을 뗄 수 없습니다.) 나쁜 습관입니까? 나는 아직도 멍청이야 – ocramz

답변

10

아마 쉽게 마지막 함수와 그 결과를 역순으로 연결하는 것은 마지막 함수에서 가져온 것입니다.

주 : compose1(defun compose1 (a) a)으로 정의 할 수 있습니다.

다소 동등하지만 덜 효율적인 버전은 왜 모든 매달려 브래킷의

(defun compose (&rest functions) 
    (if (= (length functions) 1) 
     (car functions) 
     (lambda (&rest args) 
     (funcall (first functions) 
       (apply (apply #'compose (rest functions)) 
         args))))) 
+0

예제와 설명을 가져 주셔서 감사합니다. 이것은 분명히 중요한 사항입니다! – ocramz

2

1) 결과는 (combine ...)의 결과가 다른 함수의 구성을 계산하는 함수이기 때문에 가장 바깥 쪽의 λ는 사용자를 위해 클로저를 만듭니다.

2) 가장 안쪽의 lambda는 reduce 함수에서 ists 인수를 얻습니다. Reduce는 두 인수의 함수 (가장 안쪽의 람다)를 취해이를 단계별로 목록에 적용합니다 (예 : 인수를 취하는 함수, 무엇을 그것으로 수행을 적용 :

(defun compose1 (a) 
    (lambda (&rest args) 
    (apply a args))) 

(defun compose2 (a b) 
    (lambda (&rest args) 
    (funcall a (apply b args)))) 

(defun compose3 (a b c) 
    (lambda (&rest args) 
    (funcall a (funcall b (apply c args))))) 

그래서 바깥 쪽 lambda 반환 값입니다 : 당신은 실용적인 예제의 첫 번째 몇 고려하는 경우

(reduce #'- '(1 2 3 4)) is (- (- (- 1 2) 3) 4)