17

問題のコードは次のとおりです。

(define multirember&co
  (lambda (a lat col)
    (cond
     ((null? lat)
      (col (quote ()) (quote ())))
     ((eq? (car lat) a)
      (multirember&co a
                      (cdr lat)
                      (lambda (newlat seen)
                        (col newlat
                             (cons (car lat) seen)))))
     (else
      (multirember&co a
                      (cdr lat)
                      (lambda (newlat seen)
                        (col (cons (car lat) newlat)
                             seen))))))

私はこれを一日中見つめていましたが、まったく理解できないようです。再定義している関数を再利用するcolと、例では元の定義を使用しているように見えます。どうせ変わらんでしょ。newlatパラメータとを渡さずに、どうすればそれを繰り返すことができますかseen

ピースが欠けているように見えるので、私の質問を説明するのは難しいです。おそらく誰かが本よりも明確なウォークスルーを提供できれば、それがどのように機能するかを理解できるかもしれません.

4

7 に答える 7

21

例を見てみましょう。たぶんそれが役立つでしょう。:-) 簡単にするためlistに、コレクター/継続として使用します。これは、継続への引数を含むリストを返すだけです。

(multirember&co 'foo '(foo bar) list)

開始時、

a = 'foo
lat = '(foo bar)
col = list

は空ではないため、最初の繰り返しで(eq? (car lat) a)条件が一致し、 の最初の要素はです。これにより、次の再帰が次のように設定されます。latlat'foomultirember&co

a = 'foo
lat = '(bar)
col = (lambda (newlat seen)
        (list newlat (cons 'foo seen))

次の反復では、次のように一致elseします。したがって、次の再帰では、次のようになります。latlat'bar'foo

a = 'foo
lat = '()
col = (lambda (newlat seen)
        ((lambda (newlat seen)
           (list newlat (cons 'foo seen)))
         (cons 'bar newlat)
         seen))

人間が読みやすいように (そして混乱を避けるため)、プログラムのセマンティクスを変更することなく、パラメーターの名前を変更できます (レキシカル スコープのため)。

col = (lambda (newlat1 seen1)
        ((lambda (newlat2 seen2)
           (list newlat2 (cons 'foo seen2)))
         (cons 'bar newlat1)
         seen1))

が空になったので、最後に(null? lat)節が一致します。latだから私たちは呼びます

(col '() '())

これは次のように展開されます。

((lambda (newlat1 seen1)
   ((lambda (newlat2 seen2)
      (list newlat2 (cons 'foo seen2)))
    (cons 'bar newlat1)
    seen1))
 '() '())

( and を代入するnewlat1 = '()seen1 = '()) は

((lambda (newlat2 seen2)
   (list newlat2 (cons 'foo seen2)))
 (cons 'bar '())
 '())

または (評価中(cons 'bar '()))

((lambda (newlat2 seen2)
   (list newlat2 (cons 'foo seen2)))
 '(bar)
 '())

newlat2 = '(bar)ここで、値とを代入するとseen2 = '()、次のようになります。

(list '(bar) (cons 'foo '()))

または、言い換えれば、

(list '(bar) '(foo))

の最終結果を与える

'((bar) (foo))
于 2011-08-10T01:43:32.707 に答える
8

ここで素晴らしい答えを見つけました: http://www.michaelharrison.ws/weblog/?p=34

私もこれで苦労してきました。重要なのは、レキシカル スコープ (私にとっては Javascript 風) と、eq ブランチではなく eq ブランチで multirember&co に渡される内部関数を理解することです。それを理解すると、手順全体が理解できます。

于 2011-09-07T14:15:24.367 に答える
4

上記のリンク (http://www.michaelharrison.ws/weblog/?p=34) がよく説明しているのは、この演習全体が、2 つの「ホルダー」または「コレクター」を宣言する命令型プログラミング (C、Java) の必要性を回避する方法であるということです。 " 変数 (またはリスト、ベクトル) をメモリに明示的に配置して、リストを反復処理するときに答えをキャッチします。FP 言語スキームの継続の使用では、テスト結果 (イチゴ マグロとメカジキ) を個別に作成された「バスケット」に「プッシュ」しません。代わりに、適切なコンシング関数を送信するときに、2 つのリストをコンシングしています。1 つは eq? 用です。true、eq のもう一方は? false - recurs を介して。. . 最後に、TLS の最初の例では「友達」である 3 番目の col 関数に行き着きます。これは、すべての一致を保持するために構築されたリストが空 (null?) かどうかを尋ねます。次に、TLS は、新しい「最後の」列で multirember&co を再度「実行」するように求めます。これは、すべての「マグロではない」アトムを含むリストに含まれる数 (「最後の友人」) を尋ねるだけです。つまり、2 つの別個のリストを作成し、再帰の巻き戻しの最後に、元の col ("a-friend") が最後の質問をします。おそらく、「multirember&co」という名前は、削除するアトムを除いてリストを再構築しないため、最高の名前ではありません。むしろ、2 つの別個のリスト (表示されない) を作成し、最後の col (a-friend または last-friend) を適用します。. . #t または #f を表示し、

出力は次のとおりです。

> (multirember&co 'tuna '(and tuna) a-friend)
#f
> (multirember&co 'tuna '(and not) a-friend)
#t

不一致のリストを返す列は次のとおりです。

(define list-not  (lambda (x y) x))

とその使用:

> (multirember&co 'tuna '(and not) list-not)
(and not)
于 2012-05-19T04:25:07.003 に答える
0

このチュートリアルがお役に立てば幸いです

Chris が示唆したように、newlat/seen を n/s に名前を変更し、インデックスを追加しました。この本では、関数に恐ろしい名前 (a-friend new-friend latest-fried) が付けられているので、L (ラムダ) と定義だけを残しました。

multirember&co 'tuna '(strawberries tuna and swordfish) a-friend)
  multirember&co 'tuna '(tuna and swordfish) (L(n1 s1)(a-friend (cons 'strawberries n1) s1))
    multirember&co 'tuna '(and swordfish) (L(n2 s2)((L(n1 s1)(a-friend (cons 'strawberries n1) s1)) n2 (cons 'tuna s2))
      multirember&co 'tuna '(swordfish) (L(n3 s3)((L(n2 s2)((L(n1 s1)(a-friend (cons 'strawberries n1) s1)) n2 (cons 'tuna s2)) (cons 'and n3) s3))
        multirember&co 'tuna '() (L(n4 s4)((L(n3 s3)((L(n2 s2)((L(n1 s1)(a-friend (cons 'strawberries n1) s1)) n2 (cons 'tuna s2)) (cons 'and n3) s3)) (cons 'swordfish n4) s4))

((lambda(n4 s4)((lambda(n3 s3)((lambda(n2 s2)((lambda(n1 s1)(a-friend (cons 'strawberries n1) s1)) n2 (cons 'tuna s2))) (cons 'and n3) s3)) (cons 'swordfish n4) s4)) '() '())
               ((lambda(n3 s3)((lambda(n2 s2)((lambda(n1 s1)(a-friend (cons 'strawberries n1) s1)) n2 (cons 'tuna s2))) (cons 'and n3) s3)) '(swordfish) '())
                              ((lambda(n2 s2)((lambda(n1 s1)(a-friend (cons 'strawberries n1) s1)) n2 (cons 'tuna s2))) '(and swordfish) '())
                                             ((lambda(n1 s1)(a-friend (cons 'strawberries n1) s1)) '(and swordfish) '(tuna))
                                                            (a-friend '(strawberries and swordfish) '(tuna))
于 2014-06-14T14:03:11.263 に答える