代码之家  ›  专栏  ›  技术社区  ›  Ken

控制权转移通用Lisp条件系统

  •  5
  • Ken  · 技术社区  · 14 年前

    我用其他语言编写了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)))
    

    有可能在这里做我想做的事吗?或者,让每个操作函数显式地查看其输入队列,并将值显式地放在输出队列上,这样做是否更好?

    2 回复  |  直到 14 年前
        1
  •  3
  •   Rainer Joswig Michael Fox    14 年前

    普通的通用Lisp不支持协程或向下延续。你不能跳出一些计算然后又跳回去。有图书馆(例如 cl-cont )为延续提供“一些”支持。

    SICP )抽象(使用武力和延迟)或类似的东西 SERIES (它实现了一个高效的惰性计算工具)。

        2
  •  0
  •   dmitry_vk    14 年前

    在公共Lisp中,您可以使用cl-cont库进行延续。