"за" против "каждого" в Рубине


у меня просто был быстрый вопрос относительно петель в Ruby. Есть ли разница между этими двумя способами перебора коллекции?

# way 1
@collection.each do |item|
  # do whatever
end

# way 2
for item in @collection
  # do whatever
end

просто интересно, если они точно такие же или, может быть, есть тонкая разница (возможно, когда @collection равна нулю).

7 174

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 с правильными значениями.

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