Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 356 Vote(s) - 3.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
"for" vs "each" in Ruby

#1
I just had a quick question regarding loops in Ruby. Is there a difference between these two ways of iterating through a collection?

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

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

Just wondering if these are exactly the same or if maybe there's a subtle difference (possibly when `@collection` is nil).
Reply

#2
As far as I know, using blocks instead of in-language control structures is more idiomatic.
Reply

#3
It looks like there is no difference, `for` uses `each` underneath.

$ 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
Like Bayard says, each is more idiomatic. It hides more from you and doesn't require special language features.
**Per Telemachus's Comment**

`for .. in ..` sets the iterator outside the scope of the loop, so

for a in [1,2]
puts a
end

leaves `a` defined after the loop is finished. Where as `each` doesn't. Which is another reason in favor of using `each`, because the temp variable lives a shorter period.

Reply

#4
One more different..

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

source:

[To see links please register here]


for more clear:

[To see links please register here]

Reply

#5
This is the only difference:

**each:**

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

**for:**

irb> for x in [1,2,3]; end
=> [1, 2, 3]
irb> x
=> 3

With the `for` loop, the iterator variable still lives after the block is done. With the `each` loop, it doesn't, unless it was already defined as a local variable before the loop started.

Other than that, `for` is just syntax sugar for the `each` method.

When `@collection` is `nil` both loops throw an exception:

>Exception: undefined local variable or method `@collection' for main:Object
Reply

#6
Your first example,

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

[is more idiomatic][1]. While Ruby supports looping constructs like `for` and `while`, the block syntax is generally preferred.

Another subtle difference is that any variable you declare within a `for` loop will be available outside the loop, whereas those within an iterator block are effectively private.

[1]:

[To see links please register here]

Reply

#7
See "[The Evils of the For Loop][1]" for a good explanation (there's one small difference considering variable scoping).

Using `each` is [considered more idiomatic][2] use of Ruby.

[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply

#8
I just want to make a specific point about the for in loop in Ruby. It might seem like a construct similar to other languages, but in fact it is an expression like every other looping construct in Ruby. In fact, the for in works with Enumerable objects just as the each iterator.

The collection passed to for in can be any object that has an each iterator method. Arrays and hashes define the each method, and many other Ruby objects do, too. The for/in loop calls the each method of the specified object. As that iterator yields values, the for loop assigns each value (or each set of values) to the specified variable (or variables) and then executes the code in body.

This is a silly example, but illustrates the point that the for in loop works with ANY object that has an each method, just like how the each iterator does:

class Apple
TYPES = %w(red green yellow)
def each
yield TYPES.pop until TYPES.empty?
end
end

a = Apple.new
for i in a do
puts i
end
yellow
green
red
=> nil

And now the each iterator:

a = Apple.new
a.each do |i|
puts i
end
yellow
green
red
=> nil

As you can see, both are responding to the each method which yields values back to the block. As everyone here stated, it is definitely preferable to use the each iterator over the for in loop. I just wanted to drive home the point that there is nothing magical about the for in loop. It is an expression that invokes the each method of a collection and then passes it to its block of code. Hence, it is a very rare case you would need to use for in. Use the each iterator almost always (with the added benefit of block scope).

Reply

#9
(1..4).each { |i|


a = 9 if i==3

puts a


}
#nil
#nil
#9
#nil

for i in 1..4

a = 9 if i==3

puts a

end
#nil
#nil
#9
#9

In 'for' loop, local variable is still lives after each loop. In 'each' loop, local variable refreshes after each loop.
Reply

#10
Never ever use `for` it may cause almost untraceable bugs.

Don't be fooled, this is not about idiomatic code or style issues. Ruby's implementation of `for` has a serious flaw and should not be used.

Here is an example where `for` introduces a bug,

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

Prints

quz
quz
quz

Using `%w{foo bar quz}.each { |n| ... }` prints

foo
bar
quz

Why?

In a `for` loop the variable `n` is defined once and only and then that one definition is use for all iterations. Hence each blocks refer to the same `n` which has a value of `quz` by the time the loop ends. Bug!

In an `each` loop a fresh variable `n` is defined for each iteration, for example above the variable `n` is defined three separate times. Hence each block refer to a separate `n` with the correct values.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through