稲葉です。 Inaba Hiroto wrote: > えっと、でも今のrubyのcallccがscheme(他は調べてないですが、少なくとも > GNUのscmとは)と違う振る舞いをする部分があるのを見つけてます。そのため > 今の自分のcallccによる外部iteratorは使いづらい面があります。 > 詳細は明日(すみません)ruby-devにmailします。 えっと、callccの仕様の修正をお願いしようと思っていたのでruby-devに出す つもりだったのですが、色々調べて仕様変更することはないと思い直したので このままruby-listに出します。 まず、自分が書いて原さんに単純化してもらった class Cursor def initialize(iter) @iter = iter @cont = nil end def next @cont.call if @cont @iter.call {|obj| callcc{|@cont| return obj } } nil end end ですが、色んな使い方をしようとすると破綻します。例えば c = Cursor.new([1,2,3].method(:each)) p obj = c.next p obj = c.next とすると 1 2 3 nil nil nil : nil nil cursor-by-callcc.rb:17: Interrupt と無限ループになってしまいます。別の例では以下も無限ループです。 $acc = nil def a callcc{|cc| $acc = cc; 1} end ret = a p ret $acc.call 2 p ret exit SCMでほぼ同じコード、 (define call/cc call-with-current-continuation) (define acc #f) (define (a) (call/cc (lambda (cc) (set! acc cc) 1)) ) (define ret (a)) (print ret) (acc 2) (print ret) (exit) を実行すると 1 2 とちゃんと止まります。 ところが最後の部分を (begin (define ret (a)) (print ret) (acc 2) (print ret) (exit)) とすると、これは無限ループです。 SCMはトップレベルを超えた継続をきるようです。 トップレベルが人間との会話系の場合と合わせているのかな と思いますが、本当の所はわかりません。 rubyでもそうなればいいのかなあと最初考えたのですが、 トップレベルだけそうしてもクラスやモジュールにした時 他のメソッドから呼ぶときも結局同じになるので、あまり 意味ないな、と思い直しました。 で、色々考えてCursorのcallccによる実装を作り直しました。 先のやつよりちょっと面倒になって、さらに遅くなりました。 class Cursor def initialize(iter) @iter = iter @cont = nil end def next callcc{|@cc| @cont.call if @cont @iter.call {|obj| callcc{|@cont| @cc.call(obj) } } @cc.call(nil) } end end -- 稲葉 浩人 <inaba / st.rim.or.jp>