5

以下は、私がやりたいことの非常にひどい説明であることを前もって認めます。あらかじめお詫び申し上げます。私が説明するのを助けるために質問してください。:-)

次のような個々の操作で構成される ETL (抽出、変換、読み込み) を他の言語で作成しました。

// in class CountOperation
IEnumerable<Row> Execute(IEnumerable<Row> rows) {
    var count = 0;
    foreach (var row in rows) {
        row["record number"] = count++;
        yield return row;
    }
}

次に、これらの操作をいくつかつなぎ合わせて、Operations の呼び出しとそれらの間でのデータのプッシュを担当する The Dispatcher を呼び出します。

私は Common Lisp で似たようなことをしようとしていますが、同じ基本構造を使用したいと考えています。つまり、各操作は、リストを入力してリストを出力する通常の関数のように定義されていますが、遅延しています。

define-condition条件 ( have-value) を使用して for のようyieldな動作を行うことができ、単一のループで実行でき、うまく機能します。入力をループして、同じ方法で操作を定義しています。

(defun count-records (rows)
   (loop for count from 0
         for row in rows
         do (signal 'have-value :value `(:count ,count @,row))))

問題は、いくつかの操作をつなぎ合わせて実行したい場合です。これらのディスパッチャーを作成する最初の試みは次のようになります。

(let ((next-op ...))  ;; pick an op from the set of all ops
  (loop
    (handler-bind
        ((have-value (...)))  ;; records output from operation
    (setq next-op ...)  ;; pick a new next-op
    (call next-op)))

ただし、再起動には動的な範囲しかありません。各操作には同じ再起動名があります。再起動は、関数の状態を保存するために保存できる Lisp オブジェクトではありません。これは、ハンドラ ブロック内で名前 (シンボル) で呼び出すものであり、後で使用するために保存できる継続ではありません。

ここで私がしたいことをすることは可能ですか?それとも、各操作関数がその入力キューを明示的に見て、明示的に出力キューに値を配置するだけのほうがよいでしょうか?

4

2 に答える 2

3

Plain Common Lispは、コルーチンまたは下向きの継続をサポートしていません。一部の計算から飛び出してから元に戻ることはできません。継続の「いくつかの」サポートを提供するライブラリ(たとえば、 cl-cont )があります。

'stream'のような(SICPを参照)抽象化(FORCEとDELAYを使用)またはSERIES(効率的な遅延計算機能を実装する)のようなものを使用します。

于 2010-06-01T19:49:44.780 に答える
0

ここで条件システムを使用するのは適切ではないと思います。継続すると良くなります。また、C# コンパイラは、提示されたメソッドを継続のようなオブジェクトに変換します。

Common Lisp では、cl-cont ライブラリを使用して継続を作成できます。

于 2010-06-01T03:44:45.163 に答える