"за" против "каждого" в Рубине
у меня просто был быстрый вопрос относительно петель в Ruby. Есть ли разница между этими двумя способами перебора коллекции?
# way 1
@collection.each do |item|
# do whatever
end
# way 2
for item in @collection
# do whatever
end
просто интересно, если они точно такие же или, может быть, есть тонкая разница (возможно, когда @collection
равна нулю).
7 ответов:
это единственная разница:
каждая:
irb> [1,2,3].each { |x| } => [1, 2, 3] irb> x NameError: undefined local variable or method `x' for main:Object from (irb):2 from :0
для:
irb> for x in [1,2,3]; end => [1, 2, 3] irb> x => 3
С
for
цикл, переменная итератора все еще живет после завершения блока. С помощьюeach
цикл, это не так, если он уже не был определен как локальная переменная до начала цикла.кроме этого,
for
это просто синтаксический сахар дляeach
метод., когда
@collection
иnil
обе петли бросьте исключение:исключение: неопределенная локальная переменная или метод '@collection ' для main: Object
в разделе " зло цикла For " для хорошего объяснения (есть одна небольшая разница, учитывая переменную область видимости).
С помощью
each
и считается более идиоматичным использование Ruby.
ваш первый пример,
@collection.each do |item| # do whatever end
более идиоматические. В то время как Ruby поддерживает циклические конструкции, такие как
for
иwhile
синтаксис блока, как правило, предпочтительнее.другое тонкое различие заключается в том, что любая переменная, которую вы объявляете в
for
цикл будет доступен вне цикла, в то время как те, которые находятся в блоке итератора, фактически являются частными.
еще один разных..
number = ["one", "two", "three"] => ["one", "two", "three"] loop1 = [] loop2 = [] number.each do |c| loop1 << Proc.new { puts c } end => ["one", "two", "three"] for c in number loop2 << Proc.new { puts c } end => ["one", "two", "three"] loop1[1].call two => nil loop2[1].call three => nil
источник:http://paulphilippov.com/articles/enumerable-each-vs-for-loops-in-ruby
для более ясного: http://www.ruby-forum.com/topic/179264#784884
похоже, нет никакой разницы,
for
используетeach
внизу.$ irb >> for x in nil >> puts x >> end NoMethodError: undefined method `each' for nil:NilClass from (irb):1 >> nil.each {|x| puts x} NoMethodError: undefined method `each' for nil:NilClass from (irb):4
как говорит Баярд, каждый из них более идиоматичен. Он скрывает от вас больше и не требует специальных языковых функций. за комментарий Телемаха
for .. in ..
устанавливает итератор вне области действия цикла, поэтомуfor a in [1,2] puts a end
листья
a
определяется после завершения цикла. Где какeach
- нет. Что является еще одной причиной в пользу использованияeach
, потому что переменная Temp живет более короткий срок.
никогда не используйте
for
это может приводить к ошибкам.разница тонкая, но может вызвать огромные ошибки!
не обманывайтесь, речь идет не об идиоматическом коде или проблемах стиля. Это вопрос избежания почти не отслеживаемых ошибок в производственном коде. Реализация Рубина
for
имеет серьезный недостаток и не должен использоваться. Всегда используйтеeach
петли, никогда не используйтеfor
петли.вот пример
for
вводит a баг,class Library def initialize @ary = [] end def method_with_block(&block) @ary << block end def method_that_uses_these_blocks @ary.map(&:call) end end lib = Library.new for n in %w{foo bar quz} lib.method_with_block { n } end puts lib.method_that_uses_these_blocks
печать
quz quz quz
используя
%w{foo bar quz}.each { |n| ... }
печатьfoo bar quz
почему?
на
for
цикл переменнойn
определяется один раз и только, а затем, что одно определение используется для всех итераций. Следовательно, каждый блок относится к одному и тому жеn
какое имеет значениеquz
к моменту окончания цикла. Ошибка!на
each
цикл свежей переменнойn
определяется для каждой итерации, например выше переменнаяn
определяется три раза отдельно. Следовательно, каждый блок относится к отдельномуn
с правильными значениями.