使用Fibers创建REPL

时间:2013-10-03 14:16:34

标签: ruby read-eval-print-loop fibers

我正在尝试使用Ruby的Fibers创建一个REPL,其中一个Fiber充当前端 - 输入并显示输出 - 一个Fiber作为后端 - 处理来自前端的输入并返回输出以供显示。

(我这样做的部分是因为我模糊地需要一个REPL,部分是因为我想了解Fibers,部分是因为我认为这将允许测试 - 只需替换测试框架中的前端来测试后端,而副-versa)。

麻烦的是,我找不到关于如何实际使用完整的Fibers库的任何好的文档,我的初步猜测不起作用。所以,我有四个问题:

  1. 这是一个半途而废的想法吗?我是否会在尝试从Fibers进行REPL时遇到麻烦?
  2. 我不认为没有Fibers库我就能做到这一点,因为我需要双向传递值。是吗?
  3. 有人能指出我在Ruby Fibers上的体面的,刚开始的教程或文档(如在库中,而不是单向生成器的东西)?
  4. 以下为什么不工作?它正确显示Enter a string:,并反复接受输入;但每次我提供一行输入时,它只会显示反转的第一个输入行(包括样本输出,如果不清楚的话)。
  5. 代码:

    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:")
    

    输出:

    Enter a string:
    : Hello
    
    olleH
    : World
    
    olleH
    :
    

1 个答案:

答案 0 :(得分:1)

答案,按顺序:

  1. 纤维是错误的。光纤是一种非常高级的功能,用于协作并发。将它们用于函数和块所涵盖的简单用例是没有意义的。
  2. 没有。查看您的REPL,仅使用方法编写:

    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}
    

    哪个输出:

    Enter a string:                                                                                                                      
    : Hi                                                                                                                                 
    iH                                                                                                                                   
    : Hello                                                                                                                              
    olleH
    : Bork
    kroB
    

    完美无缺。

  3. Ruby自己的文档:http://ruby-doc.org/core-2.0.0/Fiber.html

  4. 当您多次调用transferresume时,参数仅在第一次传递到光纤块时。因此,每当您调用transfer时,支持的光纤仍然会反转它传递的第一个字符串,因为它从未获得另一个字符串。这就是光纤实现这一点的错误原因。