我不明白下面是怎么回事:
counts = Hash.new(0)
File.foreach("testfile") do |line|
line.scan(/\w+/) do |word|
word = word.downcase
counts[word] += 1
end
end
counts.keys.sort.each {|k| print "#{k}:#{counts[k]} "}比以下内容更糟糕:
words = Fiber.new do
File.foreach("testfile") do |line|
line.scan(/\w+/) do |word|
Fiber.yield word.downcase
end
end
end
counts = Hash.new(0)
while word = words.resume
counts[word] += 1
end
counts.keys.sort.each {|k| print "#{k}:#{counts[k]} "}发布于 2013-05-21 05:10:14
纤程是暂停和恢复任意代码块的一种方式。像这样的示例并不是一个很好的用例,因为它并没有提供任何比传统的行读取和处理它们的方式更好的优势。
在这个特定的例子中,如果你想让它变得更好,你可以写一个枚举器风格的接口,这样你就可以写:
words = WordsReader.new("testfile")
words.each do |word|
# ...
endFibers变得重要的地方在于编写异步代码。例如,在EventMachine环境中,您需要能够发出异步调用,挂起代码块,并在收到响应时恢复它。
结果如下所示:
async_call(argument1, argument2) do |response_1|
if (response_1.ok?)
async_call(argument3, argument4) do |response_2|
if (response_2.ok?)
async_call(argument5, argument6) do |response_3|
if (response_3.ok?)
do_something(response_1, response_2, response_3)
else
panic_and_fail!
end
end
else
panic_and_fail!
end
end
else
panic_and_fail!
end
end这种嵌套的、嵌套的和重新嵌套的调用结构被松散地称为“回调地狱”,因为一旦你的逻辑变得非常重要,它就变得非常难以管理。扁平化这种结构的一种方法是使用光纤。一个适当的纤维化等价物是:
begin
response_1 = fiber_call(argument1, argument2)
response_2 = fiber_call(argument3, argument4)
response_3 = fiber_call(argument5, argument6)
do_something(response_1, response_2, response_3)
rescue NotOkay
panic_and_fail!
end纤程可以利用异常,而回调类型的代码则不能。当有效地使用异常时,可以极大地简化代码块,正如您在这里看到的那样。预期调用将抛出NotOkay类型的异常,而不是在每个响应上测试ok?。
回调不能可靠地抛出异常,因为当回调发生时,调用的发起者已经超出了范围。这是使用回调进行异步编程的一个基本限制。纤程驱动的代码维护了一个适当的调用堆栈,它只是挂起并按原样恢复,所以异常可以通过调用者正确地级联。
我发现Fibers既简单易懂,又很难正确应用。大多数情况下,您不必直接使用它们,而是使用一个使用它们的库。编写“纤程感知”代码与编写“线程安全”代码没有什么不同。这可能是一个棘手的问题。
https://stackoverflow.com/questions/16658221
复制相似问题