0

在过去的几天里,我一直在玩方案(特别是诡计)的延续,对某些函数的结果有点困惑,想知道是否有人能准确地解释这里发生了什么。

有一个调用的函数(get-token)将检索给定文件中的下一个找到的令牌。例如,如果接下来的 3 个标记是“a”、“b”和“c”,调用 (get-token) 将在第一次调用时返回“a”,在第二次调用时返回“b”,和“c”第三次被调用。

我想做的是有一个函数(peek-token),它将调用(get-token),返回令牌,然后返回到(get-token)调用函数之前的状态。我尝试了多种不同的方法来实现这一结果,我目前拥有的方法是:

;; make things a little easier to write
(define-syntax bind/cc
  (syntax-rules ()
    ((bind/cc var . body)
     (call/cc (lambda (var) . body)))))

;; function should return next token and then
;; revert to previous state
(define (peek-token)
  (bind/cc return
           (let ((token (get-token)))
             (return token))))

我现在如何理解它,bind/cc将首先保存一个延续,return然后执行以下代码块。然后当return再次被击中时,程序跳回到继续绑定的地方,并token给出值作为结果。

但是,当我运行上述函数时,结果与原始函数完全相同(get-token)

如果有人能解释我哪里出错了,或者表达一种更好的方法来获得相同的结果,我将非常感激(我知道有些人讨厌走电话/抄送的方式)。

4

1 回答 1

4

将马克吐温的错误引用撕成碎片:关于call/cc能力的报告被大大夸大了。

更具体地说,call/cc捕获调用状态,而不是程序状态。这意味着它捕获有关调用延续时代码流去向的信息。它不会捕获有关变量的信息,特别是,如果您get-token通过 ting 变量保存其迭代状态set!,则在您调用延续时不会恢复。

实际上,您的表达式(call/cc (lambda (k) (let ((token (get-token))) (k token))))应该与 simple 的行为相同(get-token);两个表达式之间不应有任何可观察到的差异。

于 2014-02-18T11:10:59.447 回答