Continuation in LISP
来源:互联网 发布:js重定向url带参数 编辑:程序博客网 时间:2024/05/20 08:43
Continuation(First-class continuation)是控制指令执行顺序的一种能力。可以用来从当前执行函数跳转回上层调用函数,或者跳转到之前以退出的函数。可以把它想象成将程序的当前状态保存下来,以便以后恢复(有点像给VM做snapshot)。但要注意的是,真正的Continuation仅仅存储执行上下文,而非程序的数据。下面是的比喻能够很好的解释这一点:
话说你在厨房的冰箱前,考虑来点三明治尝尝。如果这时候你做了个continuation,并将其存放到你的口袋中。然后你把火鸡和面包从冰箱里取出来拿到餐台,并把他们做成了你想要的三明治. 此时,如果你把你的continuation从口袋中取出来,并且调用一次的话。你会发现你突然又身处冰箱前, 考虑来点三明治尝尝. 不过,幸运的是, 此时餐台上已经有了个你想要的三明治。而火鸡和面包都不见了. 那么,你就可以径直去把它吃掉了。 :-) (有点像月光宝盒吧?)
Scheme 通过"catch" 以及 call/cc支持Continuation。Common Lisp虽然在标准中没有支持Continuation,但是通过cl-cont可以使用Delimited Continuation。(支持closure以及proper tail recursion的语言都可以实现continuation-passing style,从而实现Continuation。)
Continuation可以用来实现一些常用的设计模式,比如Coroutines (又叫做Green Thread),Exception handling等。以下给出用Scheme编写的演示代码:
1. 如何使用Continuation:
=========================================
(define the-continuation #f)
(define (test)
(let ((i 0))
; call/cc 调用它的第一个函数参数, 将一个代表当前程序
; 执行点的“continuation变量”传递给函数参数。
;
; 在这个例子中,lambda函数将continuation变量k
; 赋值给变量 the-continuation.
;
(call/cc (lambda (k) (set! the-continuation k)))
;
; 每当continuation执行的时候,我们都会回到此处执行下面的代码.
(set! i (+ i 1))
i))
=========================================
上面的代码定义了一个函数test,以及设置了the-continuation作为程序执行点的保存。
下面看一下Continuation是如何工作的:
> (test) ;调用函数test
1
> (the-continuation) ;恢复到保存点继续执行
2
> (the-continuation) ;再一次恢复到保存点继续执行
3
> (define another-continuation the-continuation) ;将continuation保存到另一个变量中
> (test) ;调用函数test, the-continuation中将保存新的程序恢复点。
1
> (the-continuation) ;调用恢复到新的保存点继续执行
2
> (another-continuation) ;恢复到旧的保存点继续执行
4
2. 通过Continuation实现Coroutines
========================================
;;; 线程调度队列. ;;; 保存一个等待执行的线程的程序执行点(continuation)列表. (define *queue* '()) (define (empty-queue?) (null? *queue*)) (define (enqueue x) (set! *queue* (append *queue* (list x)))) (define (dequeue) (let ((x (car *queue*))) (set! *queue* (cdr *queue*)) x)) ;;; 运行一个新的线程 (proc). (define (fork proc) (call/cc (lambda (k) (enqueue k) ;将(proc)执行前的点作为continuation保存到队列*queue*中 (proc)))) ;然后开始执行函数(proc) ;;; 将运行权交给队列中的其他线程,自己进入等待队列 (define (yield) (call/cc (lambda (k) ;保存放弃运行权时本线程所在的执行点(continuation)到*queue*中。 (enqueue k) ((dequeue))))) ;调用队列中第一个continuation,将执行跳转到那个continuation所保存的执行点,运行权交出。 ;;; 退出当前线程,如果所有线程以退出,则退出进程 (define (thread-exit) (if (empty-queue?) (exit) ((dequeue))))========================================
以上代码定义了一个通过Continuation实现的Coroutine的线程调度
下面看看它是如何工作的:
;;; scheme中典型的thread函数的定义: (define (do-stuff-n-print str) (lambda () (let loop ((n 0)) (format #t "~A ~A/n" str n) (yield) ;每输出一次str,就将运行权交给其他线程 (loop (1+ n))))) ;;; 创建并运行两个线程. (fork (do-stuff-n-print "This is AAA")) (fork (do-stuff-n-print "Hello from BBB")) (thread-exit)
以下是程序执行结果:
This is AAA 0 Hello from BBB 0 This is AAA 1 Hello from BBB 1 This is AAA 2 Hello from BBB 2 ...
参考资料:
http://www.scheme.com/tspl3/intro.html
http://en.wikipedia.org/wiki/Continuation
http://common-lisp.net/project/cl-cont/
- Continuation in LISP
- CLisp 20:理解On-Lisp书中的延续continuation
- Macro in LISP (LISP中宏的要义)
- Lisp in a box 安装指南
- Lisp in a box 安装指南
- Programming in Emacs Lisp笔记 编写函数
- 【转】【修改】lisp-in-a-box配置
- Lisp
- Lisp
- lisp
- LISP
- LISP
- lisp
- continuation monad
- UnicodeDecodeError: 'utf-8' codec can't decode byte 0xeb in position 114: invalid continuation byte
- 【python】'utf-8' codec can't decode byte 0xce in position 0: invalid continuation byte
- UnicodeDecodeError: 'utf8' codec can't decode byte 0xd4 in position 0: invalid continuation byte
- UnicodeDecodeError: 'utf-8' codec can't decode byte 0xcd in position 0: invalid continuation byte
- 基准比对过程和模型
- do...while(0)
- 批处理命令大全
- 《PHP Cookbook》学习笔记(六)
- usb-skeleton.c 之 12---skel_write_bulk_callback
- Continuation in LISP
- 实战Linux Bluetooth编程 (七) SDP协议
- 表格排序
- 自动选择text文字formutil.js
- linux一些命令
- 关于UI设计你需要自问的10个问题
- Struts2整合Spring2.0
- 水晶报表打印多表关联
- Spring IOC