在计划向后延续的最简单的例子没有明确的基因突变
-
13-09-2019 - |
题
我用C#编写一个小Scheme解释,并意识到,我已经实现了它的方式,这是很容易的添加适当延续支持。
所以我加入他们......但想“证明”自己的方式,我加他们是正确的。
我的Scheme解释却具有“突变”状态的支持 - 一切都是不可改变的。
因此,它是很容易编写一个单元测试,以暴露“向上”延续:
AssertEqual(Eval("(call/cc (lambda (k) (+ 56 (k 3))))"), 3);
不过,我也想写表明,如果继续“逃脱”,那么还是能够工作单元测试:
AssertEqual(Eval("(call/cc (lambda (k) k))", <some continuation>);
但当然,上述也只是测试“我得到了延续” ......不在于它实际上是一个有效的延续。
所有的例子我能找到,但最后总是使用“设置”!来演示转义延续。
什么是最简单的方案的例子,演示了向后延续适当的支持,而不依赖于基因突变?
是向下延续无突变有什么用处?我开始怀疑自己是不是,因为你只能用它来再次执行完全相同的计算......如果没有副作用,这是没有意义的。这是为什么Haskell没有延续?
解决方案
我不知道这是最简单的,但这里的使用向后延续,没有任何呼叫set!
或示例相似:
(apply
(lambda (k i) (if (> i 5) i (k (list k (* 2 i)))))
(call/cc (lambda (k) (list k 1))))
此应该求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))))
其计算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))
(曼,计算器的语法突出显示大量失败上的方案。)
其他提示
我想你是对的 - 没有突变,向后延续做任何转发延续不能
。下面是我想出来的最好的:
AssertEqual(Eval("((call/cc (lambda (k) k)) (lambda (x) 5))", 5);
不惊人,但它是一个向后延续然后我“呼叫”与实际的函数I希望调用,返回数字5的功能。
AH和我也想出这个作为一个很好的单元测试用例:
AssertEqual(Eval("((call/cc call/cc) (lambda (x) 5))", 5);
我同意Jacob B制作 - 我不认为这是没有可变状态是有用的......但依然会感兴趣的一个反例。
。<强>功能线程:强>
您可以用递归循环无突变更新状态。包括一个延续的状态被调用。现在,这是不是给其他的例子更复杂,但你真正需要的是thread-1
和main
循环。其他线程和“更新”功能,在那里显示,延续可用于比一个简单的例子更多。此外,在这个例子中工作,你需要与指定让利的实现。这可以翻译成与限定语句所做的等效形式。
示例:
(let* ((update (lambda (data) data)) ;is identity to keep simple for example
(thread-1
(lambda (cc) ;cc is the calling continuation
(let loop ((cc cc)(state 0))
(printf "--doing stuff state:~A~N" state)
(loop (call/cc cc)(+ state 1))))) ;this is where the exit hapens
(thread-2
(lambda (data) ;returns the procedure to be used as
(lambda (cc) ;thread with data bound
(let loop ((cc cc)(data data)(state 0))
(printf "--doing other stuff state:~A~N" state)
(loop (call/cc cc)(update data)(+ state 1)))))))
(let main ((cur thread-1)(idle (thread-2 '()))(state 0))
(printf "doing main stuff state:~A~N" state)
(if (< state 6)
(main (call/cc idle) cur (+ state 1)))))
,其输出
doing main stuff state:0
--doing other stuff state:0
doing main stuff state:1
--doing stuff state:0
doing main stuff state:2
--doing other stuff state:1
doing main stuff state:3
--doing stuff state:1
doing main stuff state:4
--doing other stuff state:2
doing main stuff state:5
--doing stuff state:2
doing main stuff state:6