Рубин: ломаясь от встроенного блока - PullRequest
2 голосов
/ 25 мая 2011

Обновление

Игнорировать следующее. Это оказалась ошибка, ограниченная Macruby 0.10 и, вероятно, специфичная для моей установки. Я оставлю пост на тот случай, если кто-нибудь еще столкнется с проблемой.


Мне показалось, что-то неправильно поняли про рубиновые блоки. Я хотел использовать find модуля Pathname или Find модуля, чтобы найти определенный файл в определенном дереве каталогов. Однако я не могу получить блок, предоставленный find, для возврата какого-либо значения.

С этого момента:

n= (1..10).each {|i| break i if i > 5} 
puts "n = #{n}" #=> n=6

... работает (и является обычной конструкцией) Я ожидал, что либо:

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 = 

... или:

path=Find.find(starting_directory) {|p| break p if p.include?(file_name_I_want_to_find) } 
puts "path = #{path}" #=> path = 

... будет производить только один искомый путь, но ни один не будет давать значения вообще.

Я знаю, что мой тест работает, потому что оба из следующих:

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

... работает как положено.

Почему break с find не работает так, как в первом примере?

В более общем смысле, я использую правильную технику / идиому рубина для этого обстоятельства?

Ответы [ 2 ]

2 голосов
/ 26 мая 2011

Похоже, что использование break работает на ruby-1.8.7-p334 (MRI) на OSX, а также на JRuby-1.6.1.

2 голосов
/ 25 мая 2011

Enumerable#find будет выполнять свое собственное завершение цикла, когда блок возвращает «не ложь», поэтому:

pd.find { |p| p.basename.to_s == file_name_I_want_to_find }

Независимо от того, работает ли ваша конструкция на самом деле или нет (кажется), вы этого не делаетена самом деле знаю, какой метод в конечном итоге уступил управление блоку, поэтому я думаю, что может быть трудно использовать break и продолжать вызывать поведение на основных элементах API.Я подозреваю, что их использование в качестве выражений потока управления блоками предназначено в основном для реализации, а не для границ API.

Итак, "нет", на самом деле не лучшая идиома Ruby.Вы должны использовать API напрямую.Все, что вы пытаетесь сделать, имеет прямую базовую реализацию API (и своего рода функциональную) без создания вашей собственной императивной реализации.

...