以下は、私がやりたいことの非常にひどい説明であることを前もって認めます。あらかじめお詫び申し上げます。私が説明するのを助けるために質問してください。:-)
次のような個々の操作で構成される 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 オブジェクトではありません。これは、ハンドラ ブロック内で名前 (シンボル) で呼び出すものであり、後で使用するために保存できる継続ではありません。
ここで私がしたいことをすることは可能ですか?それとも、各操作関数がその入力キューを明示的に見て、明示的に出力キューに値を配置するだけのほうがよいでしょうか?