From: matz@... (Yukihiro Matsumoto) Date: 1997-01-23T12:43:27+09:00 Subject: [ruby-list:1840] Re: command option of Tk まつもと ゆきひろです. In message "[ruby-list:1835] command option of Tk" on 97/01/23, Noritugu Nakamura writes: |中村です。 うーん,中村さん,いつ寝てるんですか? ゆうべ徹夜しちゃった んでしょうか? 体壊さないでくださいね. |とりあえず、こういうのを書きましたが |どちらのボタンを押しても 2 しか出ません。 | |#!/usr/local/bin/ruby | |require "tk" | |for i in 1..2 | text = "button" + i | TkButton.new { | text text | command proc { | print i, "\n" | STDOUT.flush | } | pack | } |end | |Tk.mainloop 以下のように書き換えてください. for i in 1..2 text = "button" + i TkButton.new { text text j = i # ここが大事 command proc { print j, "\n" # iでなくjをつかう STDOUT.flush } pack } end この点はちょっと難しいので説明しましょう. つまりtclでは文字列はその場で展開されてしまうため,-command で指定した$iの値はその時点の$iの値です.ところがrubyでは評価 は必ず実行時(ボタンが押された時)ですから,その時点のiの値(ルー プの実行が終って2になっている)が表示されます.tclでいうと "puts $i"でなく{puts $i}を指定した感じでしょうか. 望ましい処理はcommandを指定した時点でのiの値を保存しておくこ とです.こういう時に動的変数を使います.動的変数(イテレータ ブロックの中で最初に宣言された変数)はそのイテレータブロック の範囲内だけがスコープになります.つまりループの1回目の実行 と2回目の実行で,iは同じもの(値も共有する)ですが,jは一度ス コープを抜けて再度生成されたもので別々の値を持ちます. Procが絡まない時には動的変数かどうかはほとんど違いがないので すが,Procが関係すると(Procはそのスコープでの変数の値を保存 するので)結構ややこしくなります.難しければ,また質問してく ださい. まつもと ゆきひろ /:|)