call/cc 示例代码集锦

By guenchi at 2017-12-08 • 0人收藏 • 227人看过

本帖集中了网上找到的各种类型的call/cc代码,以帮助大家理解

continuation

(define the-continuation #f)
 
(define (test)
   (let ((i 0))
     ; call/cc calls its first function argument, passing
     ; a continuation variable representing this point in
     ; the program as the argument to that function.
     ;
     ; In this case, the function argument assigns that
     ; continuation to the variable the-continuation.
     ;
     (call/cc (lambda (k) (set! the-continuation k)))
     ;
     ; The next time the-continuation is called, we start here.
     (set! i (+ i 1))
     i))
(define (leaf-generator tree)
  (let ((return '()))                                       ; 1
    (letrec ((continue                                      ; 2
      (lambda ()
        (let rec ((tree tree))                              ; 3
          (cond                                             ; 4
           ((null? tree) 'skip)                             ; 5
           ((pair? tree) (rec (car tree)) (rec (cdr tree))) ; 6
           (else                                            ; 7
            (call/cc (lambda (lap-to-go)                    ; 8
                   (set! continue (lambda () 
                   (lap-to-go 'restart)))                   ; 9
                   (return tree))))))                       ;10
        (return '()))))                                     ;11
    (lambda ()                                              ;12
      (call/cc (lambda (where-to-go)                        ;13
                 (set! return where-to-go)                  ;14
                 (continue)))))))
  • 1.定义本地变量return。

  • 2.使用letrec定义continue。continue将当前叶子返回到前面,将当前继续赋给continue,并停止。

  • 3.用rec定义命名let。

  • 4.使用cond实现分支

  • 5.如果是空表,什么也不做

  • 6.如果是序对,递归地将序对的car和cdr应用于rec。

  • 7.如果是叶子,

  • 8.调用call/cc以获取当前状态(lap-to-go)

  • 9.接着将当前状态赋给continue。所以除了原有的continue,lap-to-go也包含了当前状态。

  • 10.接着函数将找到的叶子返回到函数的调用处。(return tree)应该在call/cc中以重启过程。

  • 11.在搜索了全部叶子之后返回空表。

  • 12.这是一个返回叶子生成器的生成器。

  • 13.首次调用call/cc

  • 14.将表示返回值的当前状态赋给return。

  • 15.然后调用continue。

创建可容纳任意数量fork分支的队列

(define queue '())
 
(define enqueue
    (lambda (x)
        (set! queue (append queue (list x)))))
 
(define dequeue
    (lambda ()
        (let ((x (car queue)))
            (set! queue (cdr queue))
            x)))
 
(define fork
    (lambda (proc)
        (call/cc
            (lambda (k)
                (enqueue k)
                (proc)))))
 
(define yield
    (lambda ()
        (call/cc
            (lambda (k)
                (enqueue k)
                ((dequeue))))))
 
(define run
    (lambda ()
        (if (null? queue)
            (exit)
            ((dequeue)))))
 
(define f
    (lambda (str)
        (lambda ()
            (let loop ((n 0))
                (display str )
                (display n)
                (newline)
                (yield)
                (loop (+ 1 n))))))
 
(fork (f "fork1"))
(fork (f "fork2"))
(run)


登录后方可回帖

登 录
信息栏

Scheme中文社区

推荐实现 ChezScheme / r6rs / r7rs large
theschemer.org
Q群: 724577239

精华导览

社区项目

包管理器:Raven
HTTP服务器:Igropyr (希腊火)
官方插件:vscode-chez

社区目标:

完善足以使Scheme工程化和商业化的库,特别是开发极致速度的Web服务器和ANN模块。

一直以来Scheme缺少一个活跃的中文社区,同时中文资料的稀少,导致大多数因为黑客与画家和SICP而接触Scheme的朋友,在学完SICP后无事可做,不能将Scheme转换为实际的生产力。最后渐渐的放弃。
同时Chicken等实现,却因效率问题无法与其他语言竞争。本社区只有一个目的,传播Scheme的文明之火,在最快的编译器实现上,集众人之力发展出足够与其他语言竞争的社区和库。


友情链接:

Clojure 中文论坛
函数式·China


Loading...