I'm trying to use Ruby's Fibers to create a REPL, with one Fiber acting as the frontend - taking input and displaying output - and one Fiber as backend - processing input from the frontend and returning output for display.
(I'm doing this partly because I vaguely need a REPL, partly because I wanted to understand Fibers, and partly because I figured this would allow testing - simply replace the frontend in the test framework to test the backend, and vice-versa).
Trouble is, I can't find any good documentation on how to actually use the full Fibers library, and my initial guess doesn't work. So, I have four questions:
Enter a string:
, and repeatedly accepts input; but every time I supply a line of input, it just displays the first line of input reversed (sample output is included, in case that wasn't clear).Code:
require 'fiber'
# Simple REPL. Echo back the user's input, reversed, until they
# enter "pots" (resulting in "stop")
frontend = Fiber.new do |backend, output|
while output != 'stop' do
puts output
print ": "
input = gets
output = backend.transfer(frontend, input)
end
end
backend = Fiber.new do |frontend, input|
loop do
frontend.transfer(input.reverse)
end
end
frontend.transfer(backend, "Enter a string:")
Output:
Enter a string:
: Hello
olleH
: World
olleH
:
Answers, in order:
No. Look at your REPL, written using only methods:
def repl(output, &backend)
input = nil
while output != "stop"
puts output
print ': '
input = gets.chomp
output = backend.call(input)
end
end
repl("Enter a string: ") {|input| input.reverse}
Which outputs:
Enter a string:
: Hi
iH
: Hello
olleH
: Bork
kroB
Works perfectly.
Ruby's own documentation: http://ruby-doc.org/core-2.0.0/Fiber.html
When you call transfer
or resume
multiple times, the arguments are only passed to the block of the fiber the first time. So each time you call transfer
the backed fiber is still reversing the first string it was passed, because it never got another. That's why fibers are wrong for implementing this.