What is the meaning of fibers in Ruby?

I do not understand as below:

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]} "} 

This is much worse than:

 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]} "} 
+8
multithreading ruby ruby-on-rails fibers
source share
1 answer

Fibers are a way to pause and resume arbitrary blocks of code. An example like this is actually not a very useful case, since it does not give any real advantages over the traditional way of reading lines and processing them.

In this particular example, if you want to do it better, you have to write an interface in the style of an enumerator so that you can write:

 words = WordsReader.new("testfile") words.each do |word| # ... end 

In cases where fibers are important, an asynchronous code is used in writing. For example, inside an EventMachine environment , you should be able to issue an asynchronous call, pause a block of code, and resume it when you receive a response.

It looks like this:

 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 

This kind of nested, nested, and re-nested call structure is weakly called the "callback hell", since it becomes very difficult to manage as soon as your logic becomes nontrivial. One way to smooth this structure is to use fibers. Correctly matched fiber equivalent:

 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 

Fibers can take advantage of exceptions where the callback code cannot. Exceptions when used efficiently can greatly simplify the code block, as you can see here. Instead of testing for ok? for each response, the call was expected to throw an exception of type NotOkay .

Callbacks cannot reliably throw exceptions because the call originator has already fallen out of scope during the callback. This is a fundamental limitation of asynchronous programming with callbacks. Fiber-driven code supports the appropriate call stack, it just pauses and resumes as it is, so exceptions are properly cascaded through the caller.

I found that Fibers are understandable and understandable and very difficult to use. In most cases, you do not have to use them directly, you will use a library that uses them. Writing Fiber-aware code is not much different than writing Thread-safe code. This can be difficult to do right.

+24
source share

All Articles