我开始熟悉Ruby并遇到了前所未有的功能 - callcc
我已经理解了它的一般概念,但当我试图写一个例子并且我得到了意想不到的结果时。
require 'continuation'
def callcc_func
i = 0
while true
c = nil
callcc {|x| c = x}
i += 1
puts i
return c if (i % 3) == 0
end
end
c = callcc_func()
puts
callcc_func.call
结果是无限循环。为什么呢?
我原以为是:
# for `c = callcc_func()` line
1
2
3
# callcc_func.call
4
5
6
#end here because of `return c if (i % 3) == 0`
P.S。
对不起,我的英文和谢谢。
答案 0 :(得分:2)
这个答案有点晚,但也许有人会对此感兴趣。
您只需将代码的最后一行更改为:
即可修复代码c.call
此功能的一个应用是制造发电机。这里的样本随机数生成器(取自Numerical Recipies book的常量):
def randomLCG(a,m,c,seed)
initialized = false
while true
callcc {|x| $cc = x}
if not initialized
initialized = true
return
end
seed = (a*seed + c) % m;
return seed
end
end
用法:
> randomLCG( 1664525, 2147483647 , 1013904223, 107 )
=> nil
> $cc.call
=> 1192008398
> $cc.call
=> 2079128816
> $cc.call
=> 667419302
在Python中,我们可能会使用关键字yield
来实现相同的目标(请注意,在Ruby关键字yield
中做了不同的事情):
def randLCG (a , m , c , seed):
while True:
seed = ( a∗seed + c ) % m
yield seed
用法:
>>> random = randLCG ( 1664525 , 2147483647 , 1013904223, 107 )
>>> random
<generator object randLCG at 0x7fdc790f70a0>
>>> random.next()
1192008398
>>> random.next()
2079128816
>>> random.next()
667419302
在Ruby ofc中,你可以使用闭包来解决这个问题,这样你的程序就会缩短:
require 'continuation'
def rand(a, m, c, seed)
return lambda{ seed = (a*seed + c) % m; return seed }
end
c = rand( 1664525, 2147483647 , 1013904223, 107 )
c.call
c.call
我想到的第二种用法是实施mutual recursions
。
答案 1 :(得分:1)
call-with-current-continuation
(通常缩写为call/cc
源自Scheme,所以如果您想了解更多信息,Scheme文档是一个很好的起点:
关于你的Ruby问题:看看这篇博文标题Continuations and ruby,它实现了与你想要做的非常相似的事情。你会在那里找到解释:
作为主ruby解释器运行的脚本文件,这将循环 因为它在和时捕获程序的控制状态 它被调用的地方,这包括返回继续和 然后再打电话。