首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Ruby中使用Fibers的意义是什么?

在Ruby中使用Fibers的意义是什么?
EN

Stack Overflow用户
提问于 2013-05-21 04:53:18
回答 1查看 1.5K关注 0票数 8

我不明白下面是怎么回事:

代码语言:javascript
复制
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]} "}

比以下内容更糟糕:

代码语言:javascript
复制
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]} "}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-05-21 05:10:14

纤程是暂停和恢复任意代码块的一种方式。像这样的示例并不是一个很好的用例,因为它并没有提供任何比传统的行读取和处理它们的方式更好的优势。

在这个特定的例子中,如果你想让它变得更好,你可以写一个枚举器风格的接口,这样你就可以写:

代码语言:javascript
复制
words = WordsReader.new("testfile")

words.each do |word|
  # ...
end

Fibers变得重要的地方在于编写异步代码。例如,在EventMachine环境中,您需要能够发出异步调用,挂起代码块,并在收到响应时恢复它。

结果如下所示:

代码语言:javascript
复制
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

这种嵌套的、嵌套的和重新嵌套的调用结构被松散地称为“回调地狱”,因为一旦你的逻辑变得非常重要,它就变得非常难以管理。扁平化这种结构的一种方法是使用光纤。一个适当的纤维化等价物是:

代码语言:javascript
复制
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既简单易懂,又很难正确应用。大多数情况下,您不必直接使用它们,而是使用一个使用它们的库。编写“纤程感知”代码与编写“线程安全”代码没有什么不同。这可能是一个棘手的问题。

票数 27
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16658221

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档