ささだです。

 この問題点に気付いてくれる方がいて大変喜んでいます。

 まず、継続がキャプチャする対象ですが、1.9 の実装ではすべての
ローカル変数を保存することで実現しています。1.8 では、継続では
ローカル変数は保存していませんでした。

 どうするべきなんでしょうか。継続は「こうでなければならない」
というのは、よくわかっていません。誰か、「〜だから〜であるべき
だ」という話をしてもらえないでしょうか。

 Scheme の場合ですと、

(let ((v #f))
  (call/cc (lambda (c)
             (set! v #t)
             (c #t)))
  (print v)) ;=> #t

となり、ローカル変数が変更されていることがわかります。1.8 以
前、および Scheme などとあわせるべきでしょうか。

 実装レベルの話をすると、VMスタックを簡単にコピーするだけです
ので、保存していないということです。

 実は、自分も

cont = nil
callcc{|c| cont = c
}
cont.call

というコードが動かず、少し悩んでしまいました。

 ちょっと、実装方法がうまいこと思い浮かばなかったんですが、各
スコープで binding 相当をやるようにすれば出来るのかなぁ、とは
思います。


sheepman さんは書きました:
> こんばんは、sheepman です。
> 
> trunk の callcc に関してです。
> Array#each のブロックの中で callcc を呼んだ時の、ローカル変数の
> 参照がおかしいです。
> 
> $ cat t.rb
> vv = 0
> $c = 0
> [1, 2, 3].each{|i|
>   callcc {|k| $k = k}
>   $c += 1
>   vv += 1
> }
> p [vv, $c]
> $k.call if vv < 10 and $c < 10
> 
> $ ruby-1.8 -v t.rb
> ruby 1.8.6 (2007-04-20 patchlevel 5000) [i686-linux]
> [3, 3]
> [4, 4]
> [5, 5]
> [6, 6]
> [7, 7]
> [8, 8]
> [9, 9]
> [10, 10]
> 
> $ ruby-1.9 -v t.rb
> ruby 1.9.0 (2007-05-29 patchlevel 0) [i686-linux]
> [3, 3]
> [3, 4]
> [3, 5]
> [3, 6]
> [3, 7]
> [3, 8]
> [3, 9]
> [3, 10]
> 


-- 
// SASADA Koichi at atdot dot net