익명 함수의 귀속 (2)

먼저 전편의 최종 유도 성과를 되돌아보다
n개 이상의 원소가 없는 목록은 아래의 익명 함수를 사용하여 계산할 수 있습니다.좀 그렇긴 한데 귀환까지는 아직 거리가 멀어요.
((lambda(mk-length)
   (lambda(lat)
     ((mk-length
       (mk-length            ------->  n   mk-length
        ......  
        (mk-length infinity))...) lat)))
 (lambda(length)
   (lambda(lat)
     (cond
       ((null? lat) 0)
       (else
        (+ 1 (length (cdr lat))))))))

만약 n이 0이라면 우리는 mk-length-0을 얻게 될 것이다
((lambda(mk-length)
  (mk-length infinity))
 (lambda(length)
   (lambda(lat)
     (cond
       ((null? lat) 0)
       (else
        (+ 1 (length (cdr lat))))))))

전편에서 알 수 있듯이 인피니티의 의미는 절대 호출하지 말라는 것이기 때문에 사실 인피니티가 어떤 함수인지는 우리에게 아무런 영향을 주지 않는다.그러니까 우리가 마음대로 바꿀 수 있다는 거야.
우리 는 mk-length 로 인피니티 를 바꾸었다
(lambda(mk-length)(mk-length mk-length)------>infinity를 mk-length(lambda(length)(lambda(cond--------->length-length 함수로 대체하고, 최종적으로 mk-length 형삼((null?lat)0)(else(+1(cdr lat))))))))))))
length-length를 대입한 다음 다음 다음 코드를 확장합니다.
 ((lambda(length)    (lambda(lat)      (cond               ---------->   length-length         ((null? lat) 0)        (else         (+ 1 (length (cdr lat)))))))  (lambda(length)    (lambda(lat)      (cond             ---------->   length-length         ((null? lat) 0)                 (else         (+ 1 (length (cdr lat))))))))
우리는 이어서length-length를length-length에 대입하고,계속(lambda(lat)(cond((null?lat)0)(else(+1(((lambda(length)(lambda)(cond -------------------------->length-length로 length 인삼을 교체했다.(null?lat)0)(else                     (+ 1 (length (cdr lat)))))))                    (cdr lat))))))
최종 전개 후 함수의 논리를 살펴봅시다.목록이 비어 있으면 0을 되돌려줍니다. 그렇지 않으면 1 + (length-length (cdr lat) 를 되돌려줍니다.
우리는length-length가 고급 함수라는 것을 알고 있다. 그 매개 변수는 하나의 함수이고, 되돌아오는 것은 목록을 매개 변수로 하는 또 다른 함수이다.그래서 (length-length(cdr lat)) 틀림없이 잘못 보고할 것이다.그래서 이 함수와length-0은 등가이다.이것 또한 우리가 mk-length로 인피니티를 대체하는 것이 함수의 의미에 아무런 영향을 미치지 않는다는 것을 검증했다.
이렇게 교체하는 것은 무슨 의의가 있습니까?우리는 인피니티의 의미를 고려하고 있다.우리는 이 함수가 목록의 길이를 계산하는 데 아무런 작용이 없다는 것을 알고 있다. 이 함수에 도달하기 전에 목록의 길이를 계산해야만 목록의 길이를 정확하게 얻을 수 있다.위에서 length-length를length-length에 대입한 결과를 다시 한 번 살펴보자. 얻은 것은 0개의 원소 목록 길이만 계산할 수 있는 함수이다.만약 우리 함수가 인피니티 위치에 도착했을 때 새로운length-0 함수를 생성할 수 있다면 무한히 호출할 수 있지 않겠습니까?우리는 임의의 길이 목록을 계산하는 함수를 얻지 않았습니까?
우리 mk-length-0 전개 전 상태로 돌아가자.
(lambda(mk-length)(mk-length mk-length)-------->인피니티를 mk-length(lambda(mk-length)로 바꾸었다----->우리는 형삼 이름을 바꾸었다.이것은 함수에 아무런 영향을 미치지 않습니다 (lambda (lat) (cond --------> length-length 함수, 최종적으로 mk-length형 참조 ((null?lat) 0) (else (+ 1 (mk-length (cdr lat)))))))))))))))))))))))))))
위에 녹색이 표시된 곳을 주의해라.우리가 지금 해야 할 일은 함수가 그곳에 도착하면 0원소 목록의 길이만 계산할 수 있는 새로운 함수를 얻는 것이다.이렇게 하면 함수는 우리가 목록의 길이를 계산할 때까지 무한히 먼저 갈 수 있다.위 함수 중의 mk-length는 최종적으로length-length로 대체되고, (length-length length-length)는 우리 위의 전개 과정에 따라 0원소의 목록만 계산할 수 있는 함수이다.그래서 우리는 녹색이 표시된 곳을 (mk-length mk-length)로 바꾸면 임의의 목록 길이를 계산하는 함수를 얻을 수 있다.코드는 다음과 같습니다.
((lambda(mk-length)    (mk-length mk-length))      (lambda(mk-length)        (lambda(lat)      (cond                               ((null? lat) 0)        (else         (+ 1 ((mk-length mk-length)(cdr lat))))))))
이렇게 해서 우리는 임의의 목록 길이를 계산해 낼 수 있는 함수를 얻었다.근데 이 함수는 귀속함수 같지 않아요.우리 변환해서 (mk-length mk-length) 꺼내자.함수식 프로그래밍 경험에 따르면 일단 일부 코드를 추상화하면 반드시 새로운 함수를 도입해야 한다.우리가 얻은 새로운 함수는 다음과 같다.
(lambda(mk-length)(mk-length mk-length)(lambda(mk-length)((lambda(length)-------------->새로 추상적으로 나온 함수(lambda(lat)(cond((null?lat)0)0)(else(+1(length(cdr lat)))))))))))(mk-length mk-length mk-length)))))))))))
위에 색을 표시한 코드를 보면 진정한 귀속 함수 같지 않습니까?위의 코드를 실행하면 창고가 넘칠 때까지 되돌릴 수 없습니다.원인은 추출된 (mk-length mk-length)에서 나온다.schemer는 표현식을 계산할 때, 먼저 서브 표현식을 구한 다음에 전체 표현식을 계산한다.그래서 함수는 (mk-length mk-length)의 값을 구하려고 시도하지만, 매개 변수를 직접 바꾸어 구하면 무한한 귀속을 일으킬 수 있음을 발견할 수 있다.여기에 작은 기교가 하나 있는데, 바로 '게으른 계산' 의 한 용법이다.우리가 관찰한 (mk-length mk-length)은 하나의 매개 변수만 있는 함수(위에서 우리가 전개한 최종 형태)를 되돌려준다.그래서 (mk-length mk-length)와 아래의 표현식은 등가이다.
(lambda(x)       ((mk-length mk-length) x))
여기에lisp에서 코드가 데이터라는 사상을 구현했으니 잘 체득하세요.이 표현식은 진정으로 매개 변수를 전달할 때만 진정으로 계산할 수 있다.그래서 무한귀속 문제가 생기지 않는다.다음 코드는 이 표현식(mk-length mk-length)으로 대체합니다.
(lambda(mk-length)(mk-length mk-length)(lambda(mk-length)(lambda(length)(lambda(lat)(cond((null?lat)0)0)0))------------->진짜 귀속 함수 같은 부분(else(+1(length(cdr lat)))))))))))(lambda(x)------------------>교체됨(mk-length mk-length)((mk-length mk-length) x))
지금은요, 우리는 진정으로 돌아가는 부분과 같은 부분을 다시 추출해 봅시다.
(lambda(len)((lambda(mk-length)(mk-length) (mk-length))(lambda(mk-length)(f(lambda(x)((mk-length mk-length) x)))))))))(lambda(lat)(cond-------------------------------------------------------------------------------------------------------------->매개 변수(null? lat)(lense) (lense) 0)(lelse)(lels(+ 1 (length(cdr lat))))))))
지금 우리는 주로 위에 노란색이 표시된 부분을 살펴보자.우리는 이 부분과 진정으로 목록의 길이를 구하는 논리가 이미 완전히 분리되었다는 것을 발견했다.녹색 표지 부분은 목록의 길이를 구하는 위귀환이다.왜 위귀환인가요?length는 익명 함수의 매개 변수일 뿐이기 때문에, 우리가 진정한 함수 이름을 얻을 수 없을 때 도입한 매개 변수입니다.우리는 노란색 표시 부분을 따로 꺼내서 Y로 명명했다.
(define Y(lambda(len)((lambda(f)--------->몇 글자를 적게 두드리기 위해 mk-length를 f(f)로 바꾸기(lambda(f))(len(lambda(x)(f)x)))))))))))))))
위의 이 함수가 있으면 우리는 익명 함수도 귀속시킬 수 있다.위의 이 표현식에는 매우 재미있는 이름이 있다. Y.이것은 결코 내가 마음대로 취한 것이 아니다. 그것은 바로 명성이 자자한 Y 계산이다.

좋은 웹페이지 즐겨찾기