3

現在(PocketSchemeから)R5RSスキームを学習していますが、Schemeの一部のバリアントに組み込まれている関数を使用できることがわかりましたが、すべてではありません。追加!

言い換えれば、リストを破壊的に変更することです。

リストを関数(またはベクトルや文字列)として渡してから変更するプロセスを理解するのと同じくらい、答えとして実際のコードにはあまり興味がありません。

例:

(define (append! lst var)
    (cons (lst var))
)

上記のようなアプローチを使用するときは、(define list (append! foo (bar))もっと一般的なことをしたいようなことをしなければなりません。

4

2 に答える 2

5

突然変異は許可されていますが、Schemeでは強く推奨されていません。set-car!PLTは、 andを削除することさえしましたset-cdr!(ただし、それらをset-mcar!andに「置き換え」ましたset-mcdr!)。ただし、の仕様はSRFI-1append!に登場しました。これはあなたのものとは少し異なります。SRFIでは、実装はリストを追加するために短所セルを変更する場合がありますが、必須ではありません。append!

追加されるリストの構造を変更するappend!ことが保証されているものが必要な場合は、おそらく自分で作成する必要があります。それは難しいことではありません:

(define (my-append! a b)
  (if (null? (cdr a))
      (set-cdr! a b)
      (my-append! (cdr a) b)))

定義を単純にするために、ここでエラーチェックを行う必要はありませんが、少なくとも1の長さのリストをa、(できれば)(任意の長さの)リストをとして渡す必要があることは明らかですb。理由aは少なくとも長さ1でなければなりません。これset-cdr!は、空のリストに入れることができないためです。

これがどのように機能するかに興味があるので、説明できるかどうかを確認します。基本的に、私たちがやりたいのはa、最後のconsペアである。に到達するまでリストを下に移動することです(<last element> . null)。したがって、最初aにをチェックして、がリ​​ストの最後の要素であるかどうかを最初に確認しnullますcdr。そうである場合は、追加するリストに設定するために使用set-cdr!します。これで完了です。そうでない場合は、のを呼び出す必要がmy-append!ありcdrますa。これを行うたびに、の終わりに近づきaます。これはミューテーション操作であるため、何も返さないので、変更されたリストを戻り値として作成することを心配する必要はありません。

于 2009-07-03T18:07:05.953 に答える
0

このトピックに2〜3セントを投入するのは、これまでにないほど遅くなります...

(1)変更される構造への単一の参照がある、Schemeで破壊的な手順を使用することに何も問題はありません。したがって、たとえば、単一の参照を介して断片的に大きなリストを効率的に作成し、完了したら、その(おそらく変更されない)リストをさまざまな指示対象から認識して参照できるようにします。

(2)APPENDだと思います!APPENDのように動作する必要がありますが、(潜在的に)破壊的にのみ動作します。そして、追加してください!引数として任意の数のリストを期待する必要があります。最後のリストを除く各リストは、おそらく次のリストにSET-CDR!されます。

(3)上記のAPPEND!の定義 本質的にはMacLispとCommonLispのNCONCです。(そして他のLisp)。

于 2011-03-12T03:51:48.070 に答える