# Noob Q: ruby block scoping question (ruby TK)

**URL:** <https://www.ruby-forum.com/t/noob-q-ruby-block-scoping-question-ruby-tk/136324>\
**Category:** Ruby\
**Created:** [April 30, 2008, 9:06pm UTC](https://www.ruby-forum.com/t/noob-q-ruby-block-scoping-question-ruby-tk/136324 "2008-04-30T21:06:49Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Philip\_Amadeo\_Saeli](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/e9bcb4/32.png) [@Philip\_Amadeo\_Saeli](https://www.ruby-forum.com/u/Philip_Amadeo_Saeli)\
**Post date:** [April 30, 2008, 9:06pm UTC](https://www.ruby-forum.com/t/noob-q-ruby-block-scoping-question-ruby-tk/136324/1 "2008-04-30T21:06:49Z")

</div>

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).

I’ve included below a cobbled up example that demonstrates the problem  
that has been driving me completely batty.

Basically, why is the “mybutton” method reference not contained within  
the binding of the block passed to the TkButton.new method though it is  
clearly within the scope of the initialize\_n methods?

I guess my question boils down to is how much of the block’s context is  
actually contained within its binding, i.e., how far out does it extend?  
Obviously, it extends at least to that of the method within which it  
appears. Why not to all symbols visible within the class definition  
(as, apparently, it doesn’t)?

I do realize that the actual block passed to the “command” method in the  
outer block passed to the TkButton.new method is actually executed in  
the context of the button code itself somewhere in the Tk library and,  
therefore, executes in -that- context. However, it’s binding should  
carry over some of the context in which it was created. How much (i.e.,  
to what extent)?

Any references to books, online docs, code examples, ruby interpreter  
sources, etc., in this regard would also be much appreciated.  
Additionally, any insights as to what goes on “behind the scenes” in  
ruby would be very helpful.

Thanks!

Phil

----- Begin ruby code -----  
#!/usr/bin/ruby -w

require ‘tk’

class MyButton

def myexit  
exit  
end

# Doesn’t work: “myexit” out of scope in block. Why?

def initialize\_1  
mybutton = TkButton.new do  
text “EXIT”  
command { myexit }  
pack  
end  
end

# Works: refs “myexit” outside of block.

# Note that “myexit” -is- visible within the initialize\_2 method!?!

def initialize\_2  
mybutton = TkButton.new do  
text “EXIT”  
pack  
end  
mybutton.command { myexit }  
end

# Works: creates local proc object to pass to block.

# Note that “myexit” -is- visible within the initialize\_3 method!?!

def initialize\_3  
proc\_myexit = lambda { myexit }  
mybutton = TkButton.new do  
text “EXIT”  
command proc\_myexit  
pack  
end  
end

# Pick one of “initialize\_[123]” to perform the test cases.

def initialize  
initialize\_1  
#initialize\_2  
#initialize\_3  
Tk.mainloop  
end  
end

MyButton.new  
----- End Ruby Code -----

---

<div class="post-metadata">

**Author:** ![Philip\_Amadeo\_Saeli](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/e9bcb4/32.png) [@Philip\_Amadeo\_Saeli](https://www.ruby-forum.com/u/Philip_Amadeo_Saeli)\
**Post date:** [April 30, 2008, 10:16pm UTC](https://www.ruby-forum.com/t/noob-q-ruby-block-scoping-question-ruby-tk/136324/2 "2008-04-30T22:16:59Z")

</div>

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.)

---

<div class="post-metadata">

**Author:** ![Philip\_Amadeo\_Saeli](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/e9bcb4/32.png) [@Philip\_Amadeo\_Saeli](https://www.ruby-forum.com/u/Philip_Amadeo_Saeli)\
**Post date:** [May 1, 2008, 6:50am UTC](https://www.ruby-forum.com/t/noob-q-ruby-block-scoping-question-ruby-tk/136324/3 "2008-05-01T06:50:33Z")

</div>

- Joel VanderWerf [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) [2008-04-30 20:17]:

> It’s because of #instance\_eval. The blocks you pass to Tk tend to get  
> treated like this:
> 
> tkobject.instance\_eval(&your\_block)

Thanks, Joel! You gave me just what I needed to begin to understand  
this. Looking thru ruby-talk, it seems that instance\_eval has been the  
source of quite a few questions in similar regards!

Phil

---

<div class="post-metadata">

**Author:** ![Philip\_Amadeo\_Saeli](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/e9bcb4/32.png) [@Philip\_Amadeo\_Saeli](https://www.ruby-forum.com/u/Philip_Amadeo_Saeli)\
**Post date:** [May 1, 2008, 9:08pm UTC](https://www.ruby-forum.com/t/noob-q-ruby-block-scoping-question-ruby-tk/136324/4 "2008-05-01T21:08:37Z")

</div>

Joel VanderWerf wrote:

> ```
> @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)
> }
> 
> ```

Is it possible to do ‘w.configure …’ instead of ‘@btn.configure …’?  
Why did you choose the latter?

---

<div class="post-metadata">

**Author:** ![Philip\_Amadeo\_Saeli](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/e9bcb4/32.png) [@Philip\_Amadeo\_Saeli](https://www.ruby-forum.com/u/Philip_Amadeo_Saeli)\
**Post date:** [May 1, 2008, 9:44pm UTC](https://www.ruby-forum.com/t/noob-q-ruby-block-scoping-question-ruby-tk/136324/5 "2008-05-01T21:44:39Z")

</div>

Albert S. wrote:

> > ```
> > }
> > 
> > ```
> 
> Is it possible to do ‘w.configure …’ instead of ‘@btn.configure …’?  
> Why did you choose the latter?

Sorry, bad example. Thanks for pointing that out. It should really be w.

I was trying to show that you can refer to instance variables of the  
same instance as in the outer scope. So, for example, if you had another  
button that was disabled by pressing this one, you might express that  
as:

@btn2 = …  
@btn1 = TkButton.new(btn\_frame).then { |w|  
w.command proc {  
@btn2.configure ‘state’=\>‘disabled’  
}  
}
