Scheme中向后延续的最简单示例,没有显式变异

Pau*_*rth 6 scheme continuations haskell functional-programming

我在C#中编写了一个小的Scheme解释器,并意识到我实现它的方式,很容易添加对正确延续的支持.

所以我添加了它们......但是想要"证明"我们添加它们的方式是正确的.

然而,我的Scheme解释器不支持"变异"状态 - 一切都是不可改变的.

因此编写单元测试来暴露"向上"延续非常容易:

AssertEqual(Eval("(call/cc (lambda (k) (+ 56 (k 3))))"), 3);
Run Code Online (Sandbox Code Playgroud)

但是,我还想写一个单元测试,证明如果继续"逃避",那么它仍然有效:

AssertEqual(Eval("(call/cc (lambda (k) k))", <some continuation>);
Run Code Online (Sandbox Code Playgroud)

但是,当然,上面只会测试"我得到了延续"......而不是它实际上是一个有效的延续.

然而,我能找到的所有例子总是最终使用"set!".证明逃脱的延续.

什么是最简单的Scheme示例,它展示了在不依赖突变的情况下对向后延续的适当支持?

向后延续任何使用没有变异吗?我开始怀疑自己是不是,因为你只能用它来再次执行完全相同的计算......如果没有副作用,这是没有意义的.这就是Haskell没有延续的原因吗?

Dan*_*tin 8

我不知道这是否是最简单的,但这里是一个使用向后延续而没有任何调用set!或类似的例子:

(apply
  (lambda (k i) (if (> i 5) i (k (list k (* 2 i)))))
  (call/cc (lambda (k) (list k 1))))
Run Code Online (Sandbox Code Playgroud)

这应该评估为8.

更有趣的是:

(apply
  (lambda (k i n) (if (= i 0) n (k (list k (- i 1) (* i n)))))
  (call/cc (lambda (k) (list k 6 1))))
Run Code Online (Sandbox Code Playgroud)

计算6!(也就是说,它应该评估720).

你甚至可以做同样的事情let*:

(let* ((ka (call/cc (lambda (k) `(,k 1)))) (k (car ka)) (a (cadr ka)))
      (if (< a 5) (k `(,k ,(* 2 a))) a))
Run Code Online (Sandbox Code Playgroud)

(man,stackoverflow的语法突出显示在方案上大量失败.)