二重ループ(2)

callccを使いこなせないとダメらしいので,二重ループ - ロバの耳にcallccを突っ込んでみる.これでbreakしても二重ループから脱出しない.逆にreturnでも二重ループから脱出出来ない訳だが….でもそれもcallccで解決.

def twin_loop(a,b)
  c = nil
  begin
    a.each {|x|
      skip = callcc {|c| false }
      p "skip" if skip
      b.each {|y| yield(x,y) } unless skip
      c = nil
    }
  ensure
    c.call(true) if c # 君が謝るまで殴るのをやめない!
  end
end

callcc {|ret|
  twin_loop(%w[a b c], %w[1 2 3 4]) {|l,x|
    p [l,x]
    break if l=="a" and x=="2"
    ret.call if l=="c" and x=="3"
  }
}

出力結果:

["a", "1"]
["a", "2"]
"skip"
["b", "1"]
["b", "2"]
["b", "3"]
["b", "4"]
["c", "1"]
["c", "2"]
["c", "3"]

この前のdefine_finalizerといい,かなり間違っている方向に進んでいる気がする.