문제

나는 함께 일하고있다 작은 계획서 체계를 배우고 환경에 PLT- 체계를 사용합니다.

작은 계획서 재귀로 엄청나게 도움이되었지만 (지금은 간단합니다) 나는 "수집가"를 소개하는 책의 일부에 갇히고 기능을 전체적으로 계속 부릅니다.

그들이 사용한 예제 코드는 다음과 같습니다. 나는 재귀 요소를 이해하지만 특히 람다 기능에 갇혀 있습니다. 내 마음은 길을 따라갈 수 없으며 그 람다 기능에 대한 논쟁이 어떻게 설정되는지 (그들의 유일한 부름은 재귀로 다시 전화하는 것이기 때문에, 거기에 있습니다. 기능 본문 내에서 구체적인 사용이 없습니다).

만약 누군가가 람다 수집가로의 기능을 재귀함으로써 계산 경로를 분류 할 수 있다면, 그것은 나를 도울 수있다.

;; Build a nested list of even numbers by removing the odd ones from its
;; argument and simultaneously multiply the even numbers and sum the odd
;; numbers that occur in its argument.
(define (even-only-collector l col)
  (cond
    ((null? l)
      (col (quote ()) 1 0))
    ((atom? (car l))
      (cond
        ((even? (car l))
          (even-only-collector (cdr l)
            (lambda (newl p s)
              (col (cons (car l) newl)
                (* (car l) p) s))))
         (else
           (even-only-collector (cdr l)
             (lambda (newl p s)
               (col newl
                 p (+ (car l) s)))))))
    (else
      (even-only-collector (car l)
        (lambda (al ap as)
          (even-only-collector (cdr l)
            (lambda (dl dp ds)
              (col (cons al dl)
                (* ap dp)
                (+ as ds)))))))))

;; The collector function
(define (collector newl product sum)
  (cons sum
    (cons product newl)))

미리 감사드립니다 !!

도움이 되었습니까?

해결책

이것이 어떻게 작동하는지 보려면 더 간단한 것을 시도하십시오. 예를 들어, 다음은 a의 버전입니다 list-sum 연속 인수를받는 기능 (종종 불러옵니다. k):

(define (list-sum l k)
  (if (null? l)
    ???
    (list-sum (cdr l) ???)))

기본 패턴이 있으며 누락 된 부분은 흥미로운 일이 일어나는 곳입니다. 연속 인수는 결과를 수신 할 것으로 예상되는 기능입니다. 따라서 목록이 null이면 우리가 그것을 보내야한다는 것이 분명합니다. 0, 그것이 합계이기 때문에 :

(define (list-sum l k)
  (if (null? l)
    (k 0)
    (list-sum (cdr l) ???)))

이제 목록이 null이 아닌 경우 목록의 꼬리로 기능을 재귀 적으로 호출하지만 (즉, 이것은 반복이지만) 질문은 계속해야합니다. 이것을하는 것 :

(define (list-sum l k)
  (if (null? l)
    (k 0)
    (list-sum (cdr l) k)))

분명히 잘못되었습니다. 그것은 의미합니다 k 결국 합계를 받게됩니다 (cdr l) 모든 대신 l. 대신, 새 기능을 사용하여 첫 번째 요소를 요약합니다. l 수신 한 가치와 함께 :

(define (list-sum l k)
  (if (null? l)
    (k 0)
    (list-sum (cdr l) (lambda (sum) (+ (car l) sum)))))

이것은 점점 가까워지고 있지만 여전히 잘못되었습니다. 하지만 일이 어떻게 작동하는지 생각하는 것은 좋은 점입니다. 우리는 list-sum 계속해서 전체 합계를 받고 지금 볼 수있는 첫 번째 항목을 추가 할 수 있습니다. 누락 된 부분은 우리가 무시하고 있다는 사실에서 분명합니다. k. 우리에게 필요한 것은 구성하다 k 이 기능을 사용하면 동일한 합계 작업을 수행 한 다음 결과를 k:

(define (list-sum l k)
  (if (null? l)
    (k 0)
    (list-sum (cdr l) (compose k (lambda (s) (+ s (car l)))))))

마침내 작동합니다. (BTW, 이들 각각을 기억하십시오 lambda 함수에는 자체 "사본"이 있습니다 l.) 다음과 같이 시도 할 수 있습니다.

(list-sum '(1 2 3 4) (lambda (x) x))

마지막으로 이것은 다음과 같습니다.

(define (list-sum l k)
  (if (null? l)
    (k 0)
    (list-sum (cdr l) (lambda (s) (k (+ s (car l)))))))

구성을 명시 적으로 만듭니다.

(이 코드를 중간+Lambda Student Language에서 사용하고 Stepper 버튼을 클릭하여 평가가 진행되는 방법을 확인할 수 있습니다. 이렇게하는 데 시간이 걸리지 만 연속 기능이 어떻게 중첩되는지 알 수 있습니다. 목록의 자체 견해로.)

다른 팁

다음은 "보다 구체적인 아이디어를 얻는"도움이되는 한 가지 방법이 있습니다. 수집가가 다음과 같이 정의되었다고 상상해보십시오.

(define (collector l p s)
  (display l)
  (newline)
  (display p)
  (newline)
  (display s)
  (newline))

기본 케이스에서 볼 수 있습니다. 빈 목록을 통과하면 인수와 함께 기능을 호출합니다. '(), 1, 0. 이제, 이제 하나의 요소 목록에서 작업하고 기능을 무엇으로 호출 할 것인지 확인하십시오. 무슨 일이 일어나고 있는지 알아낼 때까지 더 길고 긴 목록으로 계속 작업하십시오.

행운을 빕니다!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top