Ruby: Breaking from an Inline Block
Pregunta
Update
Ignore the following. It turned out to be a bug restricted to Macruby 0.10 and probably specific to my install. I'll leave the post in case anyone else hits the problem.
I seemed to misunderstood something about ruby blocks. I wanted to use the Pathname
or Find
module's find
to locate a specific file within a specific directory tree. However, I cannot get the block provided to find
to return any value.
Since this:
n= (1..10).each {|i| break i if i > 5}
puts "n = #{n}" #=> n=6
... works (and is a common construction) I expected that either:
starting_directory= #... a directory path
file_name_I_want_to_find= #... a file name e.g. my_file.txt
pd=Pathname.new(starting_directory)
path=pd.find{|p| break p if p.basename.to_s==file_name_I_want_to_find }
puts "path = #{path}" #=> path =
... or:
path=Find.find(starting_directory) {|p| break p if p.include?(file_name_I_want_to_find) }
puts "path = #{path}" #=> path =
... would produce just the one sought path but neither produces a value at all.
I know my test works because both of the following:
pd.find{|p| puts p if p.basename.to_s==file_name_I_want_to_find }
#=> /path/to/file_name_I_want_to_find
Find.find(starting_directory) {|p| puts p if p.include?(file_name_I_want_to_find) }
#=> /path/to/file_name_I_want_to_find
... work as expected.
Why doesn't break
with find
work the way it does in the first example?
More generally, am I using the correct ruby technique/idiom for this circumstance?
Solución
It seems that using break
works on ruby-1.8.7-p334 (MRI) on OSX, as well as JRuby-1.6.1.
Otros consejos
Enumerable#find
will do its own loop termination when the block returns "not false", so:
pd.find { |p| p.basename.to_s == file_name_I_want_to_find }
Regardless of whether your construct actually works or not (it seems to) you don't actually know which method ended up yielding control to the block, so I think it may be difficult to use break and continue to force behavior on core API elements. I suspect their use as block control flow expressions is intended mainly within an implementation rather than over API boundaries.
So, "no", that's not really the best Ruby idiom. You should use the API directly. Everything you are trying to do has a direct core API (and sort-of functional) realization without constructing your own imperative implementation.