From: Joel VanderWerf Date: 2008-05-01T05:15:35+09:00 Subject: Re: Noob Q: ruby block scoping question (ruby TK) Philip Amadeo Saeli wrote: > I've just recently been getting to know ruby and the ruby Tk library and > have run into a block scoping problem [apparently] that I don't really > understand (I'm a long-time C programmer, mostly at the systems and > library levels, and have little experience with VHLLs such as ruby). That's a really good question. It's because of #instance_eval. The blocks you pass to Tk tend to get treated like this: tkobject.instance_eval(&your_block) So all the instance variables and methods in your_block become scoped to tkobject. IMO, this was initially a very popular way of structuring a ruby lib API which has since become less popular. (Anyway, I'm less fond of it than I once was.) It is now more common for a #new method to yield the instance being constructed to the block. Nothing funny happens to the block scope, but you have to refer to the instance as the explicit receiver of messages. To emulate this kind of API with Tk, I tend to use the following construct: class Object unless method_defined?(:then) # Workaround for tk's instance_eval-ed blocks. def then yield(self) self end end end This allows you to do: @btn = TkButton.new(btn_frame).then { |w| w.text "My Button" # w must be referred to explicitly w.background get_color # calls method in expected scope w.state 'normal' w.command proc { @btn.configure 'state'=>'disabled' # @btn has expected scope } w.pack('side'=>'left', 'padx'=>10, 'pady'=>10) } This is, however, a matter of taste. (Also, I think other people call #then by a different name, like #tee or something.) -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407