From: Jay McGavren Date: 2007-04-11T04:45:05+09:00 Subject: Procs vs. nested methods and variable scope... 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?