3

HtDP の演習 30.1.1では、質問に答えるために使用を開始し、local使用するように変更しました。lambda

(define (add-to-each2 accu a-list)
  (cond
    [(empty? a-list) empty]
    [else (local ((define s (+ accu (first a-list))))
            (cons s (add-to-each2 s (rest a-list))))]))

(define (add-to-each5 accu a-list)
  (cond
    [(empty? a-list) empty]
    [else (cons ((lambda (x y)
                   (first (map + (list (first y))
                               (list x)))) accu a-list)
                (add-to-each5 (+ accu (first a-list))(rest a-list)))]))

この特定の例では、localバージョンの方が読みやすいと思います。lambdaバージョンが優先される状況はありますか? ありがとうございました。

4

1 に答える 1

3

まず、アキュムレータをインクリメントするのではなく、リストの各要素に同じ数を追加するだけなので、relative-2-absoluteと混同されている可能性があると思います。この投稿の残りの部分では、そのような場合を想定して、その増分だけを取り出します。add-to-eachadd-to-each

letローカルバインディングの最初の選択肢になると思います。あなたの例では、使用と適用lambdaをシミュレートする一般的なパターンを使用しています。letlambda

(let ([x e]) body)

以下と同等です。

((lambda (x) body) e)

例でこの変換を から に使用するlambdalet、次のようになります。

(define (add-to-each5 n a-list)
  (cond
    [(empty? a-list) empty]
    [else (cons (let ([x n] [y a-list])
                  (first (map + (list (first y))
                              (list x))))
                (add-to-each5 n (rest a-list)))]))

優れたコンパイラは、2 つの例と同じコードを生成する可能性が高いため、ほとんどの場合スタイルに依存します。お気づきのように、「左から左lambda」のパターンは読みにくい可能性があるため、私はlet.

mapただし、演​​習 30.1.1 は、各例で発生する明示的な再帰の代わりとして使用しようとしています。あなたの例では使用mapしていますが、一度に 1 つの追加のみを使用しているため、mapちょっと面倒です。(list (first y))(list x)(+ (first y) x)

mapの簡単な定義を見て、この問題に対して苦痛ではなく、どのように役立つかを見てみましょう。

(define (map f ls)
  (cond
    [(empty? ls) empty]
    [else (cons (f (first ls)) (map f (rest ls)))]))

すぐに、 とのいくつかの類似点に気付くはずですadd-to-each: の 1 行目はcond空のチェックであり、2 行目は のへの再帰呼び出しに対する要素consと関係があります。重要なのは、やりたいことを実行する を各要素に渡すことです。firstmaprestmapf

の場合、add-to-each各要素に特定の番号を追加します。を追加する例を次に示し2ます。

> (map (lambda (n) (+ 2 n)) (list 1 2 3 4 5))
(3 4 5 6 7)

maplambdaは両方とも 30.1.1 要求としてここにあり、元の の明示的な再帰なしでリスト全体に作用することに注意してください。add-to-each再帰はすべて で抽象化されていmapます。

解決策を得るにはこれで十分です。ただし、最終的な答えを教えたくありません:)

于 2011-01-19T15:50:01.157 に答える