@m_seki の

I like ruby tooから引っ越し

Fiberの使いどころ

Fiberっていうかコルーチンはこういうのに向いてるよなー。
いまなにやってるのか情報を持ち回すんじゃなくて、制御自体がそれを持っている。状態遷移マシンとか書くよりも、コルーチンでいったん休むほうがすっきり。

  class Emitter
    def initialize
      @fiber = Fiber.new do |it|
        @plist = do_pop(it)
      end
    end
    attr_reader :plist
    
    def push(it)
      @fiber.resume(it)
    end
    
    def on_value(obj)
      push(obj)
    end
    
    def on_stag(name)
      push(name.intern)
    end

    def on_etag(name)
      push(('etag_' + name).intern)
    end

    def dict
      hash = Hash.new
      while key = pop_until(:etag_dict)
        hash[key] = pop
      end
      hash
    end

    def array
      ary = Array.new
      while elem = pop_until(:etag_array)
        ary.push(elem)
      end
      ary
    end
    
    def pop_until(symbol)
      it = pop
      return it unless Symbol === it
      return nil if it == symbol
      raise RuntimeError
    end
    
    def pop
      do_pop(Fiber.yield)
    end

    def do_pop(it)
      case it
      when :dict
        dict
      when :array
        array
      else
        it
      end
    end
  end