假人的计划延续 [英] scheme continuations for dummies

查看:74
本文介绍了假人的计划延续的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于我的一生,我无法理解延续.我认为问题源于我不明白他们是干什么的事实.我在书籍或在线上找到的所有示例都是非常琐碎的.他们让我感到奇怪,为什么有人甚至想要延续?

For the life of me, I can't understand continuations. I think the problem stems from the fact that I don't understand is what they are for. All the examples that I've found in books or online are very trivial. They make me wonder, why anyone would even want continuations?

这是一个典型的不切实际的示例,来自 TSPL ,我相信这是一本公认的书.用英语,他们用计算结果将延续描述为做什么".好的,这是可以理解的.

Here's a typical impractical example, from TSPL, which I believe is quite recognized book on the subject. In english, they describe the continuation as "what to do" with the result of a computation. OK, that's sort of understandable.

然后,给出第二个示例:

Then, the second example given:

(call/cc
  (lambda (k)
    (* 5 (k 4)))) => 4 

这有什么意义?? k甚至都没有定义!当甚至无法计算(k 4)时,如何评估此代码?更不用说,call/cc如何知道将参数4提取到最里面的表达式并将其返回? (* 5 ..会发生什么?如果这个最外面的表达式被丢弃了,为什么还要写呢?

How does this make any sense?? k isn't even defined! How can this code be evaluated, when (k 4) can't even be computed? Not to mention, how does call/cc know to rip out the argument 4 to the inner most expression and return it? What happens to (* 5 .. ?? If this outermost expression is discarded, why even write it?

然后,陈述的一个较少"的琐碎示例是如何使用call/cc提供递归的非本地出口.这听起来像流控制指令,即命令式语言中的break/return,而不是计算.

Then, a "less" trivial example stated is how to use call/cc to provide a nonlocal exit from a recursion. That sounds like flow control directive, ie like break/return in an imperative language, and not a computation.

进行这些议案的目的是什么?如果有人需要计算结果,为什么不将其存储起来,以后再根据需要调用.

And what is the purpose of going through these motions? If somebody needs the result of computation, why not just store it and recall later, as needed.

推荐答案

暂时忽略call/cc.在任何编程语言中,每个表达式/语句都有一个延续-即您对结果执行的操作.例如,在C语言中,

Forget about call/cc for a moment. Every expression/statement, in any programming language, has a continuation - which is, what you do with the result. In C, for example,

x = (1 + (2 * 3)); 
printf ("Done");

的数学分配为printf(...)(2 * 3)的延续是加1;分配给x; printf(...)'.从概念上讲,无论您是否有权使用此延续.考虑一下您需要什么信息来继续操作-这些信息是1)堆内存状态(通常),2)堆栈,3)任何寄存器和4)程序计数器.

has the continuation of the math assignment being printf(...); the continuation of (2 * 3) is 'add 1; assign to x; printf(...)'. Conceptually the continuation is there whether or not you have access to it. Think for a moment what information you need for the continuation - the information is 1) the heap memory state (in general), 2) the stack, 3) any registers and 4) the program counter.

因此存在延续,但通常它们只是隐式的,无法访问.

So continuations exist but usually they are only implicit and can't be accessed.

在Scheme和其他几种语言中,您可以访问延续.本质上,在后台,编译器+运行时捆绑了继续所需的所有信息,将其存储(通常存储在堆中)并为您提供了处理方法.您获得的句柄是函数"k"-如果调用该函数,您将在call/cc点之后继续.重要的是,您可以多次调用该函数,并且总是在call/cc点之后继续.

In Scheme, and a few other languages, you have access to the continuation. Essentially, behind your back, the compiler+runtime bundles up all the information needed for a continuation, stores it (generally in the heap) and gives you a handle to it. The handle you get is the function 'k' - if you call that function you will continue exactly after the call/cc point. Importantly, you can call that function multiple times and you will always continue after the call/cc point.

让我们看一些示例:

> (+ 2 (call/cc (lambda (cont) 3)))
5

在上面,call/cc的结果是lambda的结果,即3.未调用延续.

In the above, the result of call/cc is the result of the lambda which is 3. The continuation wasn't invoked.

现在让我们调用延续:

> (+ 2 (call/cc (lambda (cont) (cont 10) 3)))
12

通过调用延续,我们在调用后跳过任何内容,并直接在call/cc点继续.使用(cont 10)继续返回10,该值与12的2相加.

By invoking the continuation we skip anything after the invocation and continue right at the call/cc point. With (cont 10) the continuation returns 10 which is added to 2 for 12.

现在让我们保存延续.

> (define add-2 #f)
> (+ 2 (call/cc (lambda (cont) (set! add-2 cont) 3)))
5
> (add-2 10)
12
> (add-2 100)
102

通过保存延续,我们可以随意使用它,以跳回" call/cc点之后的任何计算.

By saving the continuation we can use it as we please to 'jump back to' whatever computation followed the call/cc point.

通常,延续用于非本地出口.考虑一个将要返回列表的函数,除非在出现问题时将返回'().

Often continuations are used for a non-local exit. Think of a function that is going to return a list unless there is some problem at which point '() will be returned.

(define (hairy-list-function list)
  (call/cc
    (lambda (cont)
       ;; process the list ...

       (when (a-problem-arises? ...)
         (cont '()))

       ;; continue processing the list ...

       value-to-return)))

这篇关于假人的计划延续的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆