我用其他语言编写了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;
}
}
然后将这些操作串在一起,并调用调度程序,后者负责调用操作并在它们之间推送数据。
我试图在commonlisp中做一些类似的事情,我想使用相同的基本结构,也就是说,每个操作都定义为一个普通函数,它输入一个列表,输出一个列表,但是很懒。
我可以
define-condition
have-value
)用于
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)))
有可能在这里做我想做的事吗?或者,让每个操作函数显式地查看其输入队列,并将值显式地放在输出队列上,这样做是否更好?