# Procs vs. nested methods and variable scope

**URL:** <https://www.ruby-forum.com/t/procs-vs-nested-methods-and-variable-scope/91619>\
**Category:** Ruby\
**Created:** [April 10, 2007, 9:46pm UTC](https://www.ruby-forum.com/t/procs-vs-nested-methods-and-variable-scope/91619 "2007-04-10T21:46:10Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jay\_McGavren](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e79b87/32.png) [@Jay\_McGavren](https://www.ruby-forum.com/u/Jay_McGavren)\
**Post date:** [April 10, 2007, 9:46pm UTC](https://www.ruby-forum.com/t/procs-vs-nested-methods-and-variable-scope/91619/1 "2007-04-10T21:46:10Z")

</div>

I’m going to be re-using this technique at quite a few places in my  
code, so I want to be certain I have it right…

I started with code like this, within a method:

for playlist in playlists  
with\_option\_values(‘find’, config) do |terms|  
if (results = playlist.Search(terms, 0))  
results.each {|track| tracks.push(track)}  
end  
end  
with\_option\_values(‘visible-find’, config) do |terms|  
if (results = playlist.Search(terms, 1))  
results.each {|track| tracks.push(track)}  
end  
end  
#Repeat several more times…  
end

I of course hate repeating myself like that. I don’t want to create a  
super-specialized instance or class method, though. So I tried a  
nested method:

for playlist in playlists  
def search\_playlist(playlist, option, config, field\_id, tracks)  
with\_option\_values(option, config) do |terms|  
if (results = playlist.Search(terms, field\_id))  
results.each {|track| tracks.push(track)}  
end  
end  
end  
search\_playlist(playlist, ‘find’, config, 0, tracks)  
search\_playlist(playlist, ‘visible-find’, config, 1, tracks)  
#Repeat several more times…  
end

…I wanted to do search\_playlist(option, field\_id), but I had to add  
parameters for the playlist, config, and tracks as well, because they  
fall out of scope when the method is called. Yuck!

So finally, I went with a Proc, because I know a block/Proc stores all  
variables that are in scope when it’s defined:

for playlist in playlists  
search\_playlist = lambda {|option, field\_id|  
with\_option\_values(option, config) do |terms|  
if (results = playlist.Search(terms, field\_id))  
results.each {|track| tracks.push(track)}  
end  
end  
}  
search\_playlist.call(‘find’, 0)  
search\_playlist.call(‘visible-find’, 1)  
#Repeat several more times, with a lot less typing.  
end

search\_playlist falls out of scope when the enclosing method ends, so  
I think I’m safe from playlist, tracks, etc. living forever on the  
stack, right? Also, how bad is it that I’m creating the Proc inside a  
(not very tight) loop?

---

<div class="post-metadata">

**Author:** ![Jay\_McGavren](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e79b87/32.png) [@Jay\_McGavren](https://www.ruby-forum.com/u/Jay_McGavren)\
**Post date:** [April 11, 2007, 12:52am UTC](https://www.ruby-forum.com/t/procs-vs-nested-methods-and-variable-scope/91619/2 "2007-04-11T00:52:29Z")

</div>

On Apr 10, 2007, at 3:45 PM, Jay McGavren wrote:

> ```
> end
> with_option_values('visible-find', config) do |terms|
> if (results = playlist.Search(terms, 1))
> results.each {|track| tracks.push(track)}
> end
> end
> #Repeat several more times...
> 
> ```
> 
> end

What is that second argument to Search? Is it just an index of  
some sort such that ‘find’ is the first search (index 0) and  
‘visible-find’ is the second search (index 1) and so on? Also,  
it is a bit strange to have a method capitalized.

If you change the definition of Search to return an empty array  
instead of nil or false when it finds no matches and that second  
argument to Search is just an index as I described then I think  
you can wrap everything up as:

results = []  
playlists.each do |playlist|  
%w{find visible-find}.each\_with\_index do |option, index|  
with\_option\_values(option, config) do |terms|  
results += playlist.Search(terms, index)  
end  
end  
end

No need to create methods or procs.

I tossed the (for…in) constructs since ‘each’ is more Ruby-like  
but you could easily use for…in if that reads better to you.

And if you like using inject:

results = playlists.inject([]) do |list, playlist|  
%w{find visible-find}.each\_with\_index do |option, index|  
with\_option\_values(option, config) do |terms|  
list += playlist.Search(terms, index)  
end  
end  
end

If the second argument to Search is not strictly increasing with  
the option names you could iterate over an array of values:

[[‘find’, 0], [‘visible-find’, 1], [‘other-opt’, 5]].each do |  
option, search|  
#…  
end

If you need Search to return nil you could do something like:

```
   results += playlist.Search(terms, index) || []

```

Gary W.

---

<div class="post-metadata">

**Author:** ![Jay\_McGavren](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e79b87/32.png) [@Jay\_McGavren](https://www.ruby-forum.com/u/Jay_McGavren)\
**Post date:** [April 11, 2007, 10:11am UTC](https://www.ruby-forum.com/t/procs-vs-nested-methods-and-variable-scope/91619/3 "2007-04-11T10:11:12Z")

</div>

On Apr 10, 3:50 pm, Gary W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On Apr 10, 2007, at 3:45 PM, Jay McGavren wrote:
> 
> > ```
> > if (results = playlist.Search(terms, 0))
> > results.each {|track| tracks.push(track)}
> > end
> > 
> > ```

…

> What is that second argument to Search? Is it just an index of  
> some sort such that ‘find’ is the first search (index 0) and  
> ‘visible-find’ is the second search (index 1) and so on? Also,  
> it is a bit strange to have a method capitalized.

playlist is actually a WIN32OLE object (type iTunes.Application), and  
that’s the form the generated methods took. The numbers/field ID  
would actually be a constant with an English name (‘search all fields’  
or similar in this case) if we were working in C++ and had imported a  
header file.

Anyway, thanks for the pointers; I’ll look 'em over and see what I can  
incorporate.
