익명 함수의 귀속 (1)

먼저 다음과 같은 함수를 정의합니다.
(define length
  (lambda(lat)
    (cond
      ((null? lat) 0)
      (else
       (+ 1 (length (cdr lat)))))))

이 함수는 매우 간단하다. 단지 하나의 매개 변수만 있다.기능은 매개 변수lat의 길이를 구하는 것이다.
다음은 호출 예입니다.
> (length '(2 3 4))
3

이 함수는 신기한 점이 없다. 우리는 다음 두 가지 문제를 생각하자.
귀속은 무엇입니까?
이 문제는 대답하기 쉽다. 간단하게 말하면 함수 자체가 자신을 호출하는 것이다.
2. 익명 함수는 귀속을 어떻게 사용합니까???
이 문제는 말이야.위의 예에서 우리는 함수에 length라는 이름을 지어주었는데, 귀속 호출할 때 바로 length로 함수 자체를 대체했다.만약 우리의 함수에 이름이 없다면, 어떻게 귀속을 사용합니까?
먼저 infinity라는 함수를 정의합니다.
(define infinity
  (lambda()
    (infinity)))

이 함수는 호출만 하면 창고가 넘칠 때까지 나올 수 없다.이 함수는 무슨 소용이 있습니까?일단 내려봐!
익명 함수를 정의합니다.
(lambda (lat)
   (cond
     ((null? lat) 0)
     (else(infinity))))

이 익명 함수는 매개 변수lat가 필요합니다.목록lat가 비어 있으면 0을 되돌려줍니다.그렇지 않으면 인피니티 함수를 실행합니다.우리는 인피니티가 밑도 끝도 없는 구멍이라는 것을 안다.그래서 인피니티를 호출하는 잠재적 의미는 절대로 여기에 실행할 수 없다는 것이다.그럼 이 함수는 또 무슨 소용이 있습니까?다음으로 이동하겠습니다.
((lambda (lat)
   (cond
     ((null? lat) 0)
     (else(infinity)))) '())

결과 반환: 0
((lambda (lat)
   (cond
     ((null? lat) 0)
     (else(infinity)))) '(1))

인피니티가 실행되었기 때문에, 함수가 창고가 넘칠 때까지 되돌릴 수 없습니다.그래서 이 익명 함수의 유일한 역할은 0개의 원소의 목록 길이를 측정하는 것이다.우리는 이 익명 함수를 먼저length-0이라고 부른다. (0 개의 원소 목록을 포함하는 함수만 측정할 수 있다.)
익명 함수를 다시 정의합니다.
(lambda (lat)
  (cond
    ;; , 0
    ((null? lat) 0)
    (else
     ;;  1 + (length-0  )
     (+ 1 ((lambda(lat)
            (cond
              ((null? lat) 0)
              (else
               (infinity)))) (cdr lat))))))
이 함수는length-0보다 좀 복잡하다. 우리는 그것이 가장 많은 원소를 포함하는 목록의 길이를 측정할 수 있다는 것을 발견했다.원소보다 큰 목록을 가져오면 함수는 인피니티로 실행됩니다.그래서 우리는 length-1이라고 부른다
이 사고방식에 따라 우리는 length-2를 정의한다.
(lambda (lat)
  (cond
    ;; , 0
    ((null? lat) 0)
    (else
     ;;  1 + (length-1  )
     (+ 1 ((lambda (lat)
            (cond
              ;; , 0
              ((null? lat) 0)
              (else
               ;;  1 + (length-0  )
               (+ 1 ((lambda(lat)
                       (cond
                         ((null? lat) 0)
                         (else
                          (infinity)))) (cdr lat)))))) (cdr lat))))))
이 함수는 보기에 복잡하지만 사실 사고방식이 매우 고정되어 순서대로length-1과length-0을 호출한다.이 함수는 두 요소보다 많지 않은 목록의 길이만 계산할 수 있다.
상기 세 열자의 사고방식을 통해 우리는 목록의 길이를 계산하는 함수를 정의할 수 있다. 전제는 목록에 들어오는 최대 길이를 알아야 한다는 것이다.한 마디로 하면 지원 목록의 길이가 증가함에 따라 함수의 부피는 점점 거대해지고 읽기 어려워진다.length-2를 살펴보고 발견한 것이 있는지 살펴보자.
(lambda (lat)   (cond     ((null? lat) 0)     (else      (+ 1 ((lambda (lat)             (cond               ((null? lat) 0)               (else                (+ 1 ((lambda(lat)                        (cond                          ((null? lat) 0)                          (else                           (infinity)))) (cdr lat)))))) (cdr lat))))))
우리는 색깔을 표시하는 부분이 똑같다는 것을 발견했다. 이것은 이 코드들이 비록 매우 복잡하지만 패턴이 확실히 같다는 것을 설명한다.이런 코드는 우리가 어떤 기술을 사용할 수 있었지?추상적이지.
더 가까운 단계에서 우리는 위의 변화가 바로 아래의 xxx의 변화라는 것을 발견했다. length-1length-0에서 infinity까지.
(lambda(lat)   (cond     ((null? lat) 0)     (else      (+ 1 xxx (cdr lat)))))
우리는 먼저 첫 번째 추상적인 시도를 한다. 우리는length-length라고 해도 무방하다.
(lambda(length)   (lambda(lat)   (cond     ((null? lat) 0)     (else      (+ 1 (length (cdr lat)))))))
여기의length는 하나의 함수, 즉 위의 xxx를 대표한다.우리는 그것을 추상화할 것이다.대상 프로그래밍에서 추상적인 것은 그것을 하나의 종류로 봉인하는 것이다.함수 프로그래밍에서 추상은 그것을 하나의 단독 함수로 추상화하는 것이다.위에서 우리가 얻은length-length는 고급 함수입니다. 우리는 하나의 함수를 전달합니다. 되돌아오는 값은 함수입니까? 아니면 함수입니까?
저희가 length-length로 length-0을 다시 정의할게요.
((lambda(length)
  (lambda(lat)
  (cond
    ((null? lat) 0)
    (else
     (+ 1 (length (cdr lat)))))))
 infinity)
length-length를 호출했는데 매개 변수는 infinity입니다.표현식을 살펴보겠습니다.
;;length-length infinity   length-length-0
(lambda(lat)
  (cond
    ((null? lat) 0)
    (else
     (+ 1 (infinity (cdr lat))))))

;; length-0
(lambda (lat)
   (cond
     ((null? lat) 0)
     (else(infinity))))

어떤 사람은 이length-0이 다르다고 하니 잊지 마세요.infinity는 절대 호출할 수 없습니다. 이 두 코드의 기능은 아무런 차이가 없습니다.물론 우리는 최초에length-0을length-length-0이라는 형식으로 정의할 수 있다.
이제 length-length로 length-1을 정의할게요.
((lambda(length)   (lambda(lat)   (cond                           -------->  length-length     ((null? lat) 0)     (else      (+ 1 (length (cdr lat)))))))  (lambda(lat)   (cond     ((null? lat) 0)              --------->  length-length-0     (else      (+ 1 (infinity (cdr lat)))))))
length-length-0을 length-length에 전달하는 거예요.
다시 length-2를 정의해 보세요. 여러분이 맞혀보시면 length-1을 length-length에 전달할 거예요.
저희가 length-length-2를 받았습니다. 아래와 같습니다.
((lambda(length)    (lambda(lat)      (cond        ((null? lat) 0)       --------->  length-length        (else         (+ 1 (length (cdr lat)))))))  ((lambda(length)     (lambda(lat)       (cond         ((null? lat) 0)         (else          (+ 1 (length (cdr lat)))))))   -------------> length-length-0   (lambda(lat)     (cond       ((null? lat) 0)       (else        (+ 1 (infinity (cdr lat))))))))
복잡해 보이지만 규칙성이 있다.우리는 계속해서 length-length-2를 관찰한 결과 여전히 대량의 중복 코드가 존재하는 것을 발견했다.
(lambda(length)(lambda(lat)(cond((null?lat)0)------>length-length-2의 최외층 length-length(else(+1(length(cdr lat))))))))))))(lambda(length)(cond-------------->length-length-1의 최외층 length-length(null)?(else(+1(cdr lat))))((lambda(length)))))(lambda(lat)(cond------------->length-length-0의 최외층 length-length((null?lat)0) (else(+1(length(cdr lat)))) infinity))
우리는 Length-length-2를 약간 개조했다. 바로 Length-0을 전개 전의 모델로 복원하는 것이다. 이렇게 하면 더욱 뚜렷하게 보인다.색을 표시하는 코드가 똑같습니다.허허, 우리는 DRY라는 원칙을 명심하고 추상적인 순간에 이르렀다.아직도 기억하는 함수식 프로그래밍에서 어떻게 추상적입니까?우리는 계속해서 같은 부분을 함수로 추상화했다.공유된 부분은 바로length-length다.
우리length-0을 다시 정의해 보자. 이것은 이미 세 번째 추상이다.두 번째는length-length-0이다.세 번째 추첨은 저희가 이걸 mk-length-0이라고 해요.
(lambda(mk-length)(lambda(lat)---------->length-length를 mk-length로 대체하여 펼치면,우리는length-length-0((mk-length infinity))(lambda(length))(lambda(lat)(cond---------------------->length-length(우리는 단독으로 뽑았다)((null?lat)0)(else(+1(length(cdr lat)))))))))))
아래는 약간 빙빙 돌지만 복잡하지는 않다.위의 녹색 코드를 주의하십시오. 우리는 mk-length를 인피니티에 작용할 것입니다. 우리는 length-length-0을 얻었습니다.여기 mk-length가 바로 length-length입니다.우리가 length-length-1을 어떻게 얻었는지 기억나?length-length를 length-length-0에 작용하는 것이다.그래서 우리는 mk-length가 length-length-0에 작용하면 length-length-1을 얻을 수 있다.즉, mk-length를 (mk-length infinity)에 작용하면 우리는 length-length-1을 얻는다.
ok, 위의 분석이 있으면length-1을 다시 정의해 봅시다. mk-length-1이라고 합니다.
((lambda(mk-length)    (lambda(lat)      ((mk-length        (mk-length infinity)) lat)))    (lambda(length)    (lambda(lat)      (cond        ((null? lat) 0)        (else         (+ 1 (length (cdr lat))))))))
mk-length-0에 비해 mk-length-1은 위에 노란색이 표시된 곳만 변화가 생기고 나머지는 변하지 않는다.이번에는 추상적으로 괜찮은데, 마침내 좀 모양이 잡혔다.
같은 이치로length-2를 재정의하여 mk-length-2라고 부른다
(lambda(mk-length)(lambda(lat)((mk-length)(mk-length----------->유일하게 변화하는 곳(mk-length infinity))lat)(lambda(length)))(lambda(lat)(cond((null?lat)0)0)(else(+1(length(cdr lat)))))))))))))))))
mk-length-n 정의?so easy !!
(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=100000, 이 함수는 아무도 쓰기를 원하지 않을 것입니다. 계속 목표를 향해 노력해야 합니다.무슨 목표였지?사용귀환이야.

좋은 웹페이지 즐겨찾기