どうも、Ruby のバグのような気がするものを見つけたのですが、もしかした
らそうでないような気もするので、教えて下さい。

(スクリプト全体は後につけますが) 次のようなコードを実行すると、
print "#{var}\n" の行で var という変数が定義されていないというエラーが
出ます。

test = Test.new
Retriever.new {|retriever|
  var = "val"
  test.get(retriever) {|result|
    print "#{result}\n"
    print "#{var}\n"
  }
}

実際のエラーメッセージは次のようになります。

% ./tst
test
./tst:52: undefined local variable or method `var' for #<Object:0x8106cd8> (NameError)
        from ./tst:31:in `join'
        from ./tst:31:in `initialize'
        from ./tst:48:in `new'
        from ./tst:48
% /usr/local/bin/ruby -v
ruby 1.6.1 (2000-09-27) [i386-freebsdelf4.0]
% 

| ローカル変数のスコープは,その変数が宣言されたブロック,メソッド定義,
| またはクラス/モジュール定義の終りまでです.寿命もそのブロックの終りま
| で(トップレベルのローカル変数はプログラムの終了まで)ですが,例外として
| ブロックが手続きオブジェクト化された場合は,そのオブジェクトが消滅する
| まで存在します.同じスコープを参照する手続きオブジェクト間ではローカル
| 変数は共有されます.

という説明を読むと、この「例外」に対応するので、ちゃんと生き残っていて
使えるべきだ、と思うのですが...

#!/usr/local/bin/ruby

require 'thread'
require 'net/http'

class Test
  def get(retriever)
    Receptor.new(retriever) {|result|
      yield result
    }
  end
end

class Receptor
  def initialize(retriever, &proc)
    @proc = proc
    retriever.enqueue(self)
  end

  def finished
    @proc.call(:test)
  end
end

class Retriever
  def initialize
    @queue = Queue.new
    @thread = Thread.new {get_loop}
    yield self
    @queue.push(nil)
    @thread.join
  end

  def enqueue(dest)
    @queue.push dest
  end

  def get_loop
    while dest = @queue.pop
      r, b = Net::HTTP.new("cvs.m17n.org", 80).get("/")
      dest.finished
    end
    @queue.push nil
  end
end

test = Test.new
Retriever.new {|retriever|
  var = "val"
  test.get(retriever) {|result|
    print "#{result}\n"
    print "#{var}\n"
  }
}
-- 
[田中 哲][たなか あきら][Tanaka Akira]
「ああ、それは大丈夫だよぉ。カイロを持って行くもぉん$(C⊇」
  (気象精霊記2 爆弾気分の低気圧, 清水文化)