用于控制权转移的 Common Lisp 条件系统

发布于 2024-09-03 07:19:02 字数 1270 浏览 2 评论 0原文

我首先承认,以下是对我想做的事情的非常糟糕的描述。提前致歉。请提出问题来帮助我解释。 :-)

我已经用其他语言编写了 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;
    }
}

然后将许多这些操作串在一起,并调用 Dispatcher,它负责调用 Operations 和在它们之间推送数据。

我正在尝试在 Common Lisp 中做类似的事情,并且我想使用相同的基本结构,即每个操作都被定义为一个输入列表并输出列表的普通函数,但是是惰性的。

我可以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)))

但是重新启动只有动态范围:每个操作都将具有相同的重新启动名称。重新启动不是我可以存储的 Lisp 对象,用于存储函数的状态:它是您在处理程序块内通过名称(符号)调用的东西,而不是您可以存储以供以后使用的延续。

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

I'll admit right up front that the following is a pretty terrible description of what I want to do. Apologies in advance. Please ask questions to help me explain. :-)

I've written ETLs (Extract, Transform, Load) in other languages that consist of individual operations that look something like:

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

Then you string a number of these operations together, and call The Dispatcher, which is responsible for calling Operations and pushing data between them.

I'm trying to do something similar in Common Lisp, and I want to use the same basic structure, i.e., each operation is defined like a normal function that inputs a list and outputs a list, but lazily.

I can define-condition a condition (have-value) to use for yield-like behavior, and I can run it in a single loop, and it works great. I'm defining the operations the same way, looping through the inputs:

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

The trouble is if I want to string together several operations, and run them. My first attempt at writing a dispatcher for these looks something like:

(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)))

But restarts have only dynamic extent: each operation will have the same restart names. The restart isn't a Lisp object I can store, to store the state of a function: it's something you call by name (symbol) inside the handler block, not a continuation you can store for later use.

Is it possible to do something like I want here? Or am I better off just making each operation function explicitly look at its input queue, and explicitly place values on the output queue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

三寸金莲 2024-09-10 07:19:02

Plain Common Lisp 不支持协程或向下延续。您无法跳出某些计算然后再跳回来。有一些库(例如 cl-cont )为延续提供“一些”支持。

我会使用类似“stream”的方式(参见 SICP)抽象(使用 FORCE 和 DELAY)或类似 SERIES (实现高效的惰性计算工具)。

Plain Common Lisp does not support coroutines or downward continuations. You can't jump out of some computation and then jump back in. There are libraries (for example cl-cont) to provide 'some' support for continuations.

I would use 'stream'-like (see SICP) abstractions (using FORCE and DELAY) or something like SERIES (which implements an efficient lazy computation facility).

所有深爱都是秘密 2024-09-10 07:19:02

我认为条件系统不适合在这里使用。继续下去会更好。此外,C# 编译器会将您提供的方法转换为类似延续的对象。

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

I don't think that condition system is the right thing to use here. It'll be better with continuations. Also, C# compiler turns the method you presented into a continuation-like object.

In Common Lisp, you can make continuations with cl-cont library.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文