I know that for i in arr
slightly differs from arr.each
scope and everyone keeps saying that iterators are preferrable, but I wonder if there is any case when cycle is preferrable and why it is (since iterators are more idiomatic)?

- 3,903
- 1
- 26
- 37
-
3When prototyping in Ruby with intent to speed up with C extensions, I find it helps to use more C-like idioms, there is less to convert. But probably not the answer you are looking for . . . – Neil Slater Nov 25 '13 at 16:51
-
2This comment is not intended as an answer, merely giving some additional information. According this [this answer](http://stackoverflow.com/a/3294543/877472), both `for` and `each` use `.each` in the background. The main difference (according to [this answer from the same question](http://stackoverflow.com/a/3294561/877472) ) is how the iterator variable is scoped. Ultimately, other than the Neil Slater's post, it sounds like there may not be any technical reason to prefer one over the other except. – Paul Richter Nov 25 '13 at 17:24
2 Answers
TL;DR
- Use
for
loop for performance in Ruby 1.8 - Use
for
loop to standards in existing projects - Use
each
loop to minimize side effects - Prefer
each
loop.
each
minimizes side effects
The primary difference between for
and each
is scoping.
The each
function takes a block. Blocks create a new lexical scope. This means that any variables declared within the scope of the function will no longer be available after the function.
[1, 2, 3].each do |i|
a = i
end
puts a
# => NameErrror: undefined local variable or method `a' for main:Object
Whereas:
for i in [1, 2, 3]
a = i
end
puts a
# => 3
Thus, using the each
syntax minimizes the risk of side effects.
Determing exit point?
This said, there are special instances where the for
loop may be helpful. Specifically, when finding out where a loop exited.
for i in 1..3
a = i
break if i % 2 == 0
end
puts a
# => 0
There is a better way to do this though:
a = (1..3).each do |i|
break i if i % 2 == 0
end
Each is faster (in Ruby 2.0)
Benchmark.bm(8) do |x|
x.report "For" do
max.times do
for i in 1..100
1 + 1
end
end
end
x.report "Each" do
max.times do
(1..100).each do |t|
1+1
end
end
end
end
Ruby 2.0
user system total real
For 6.420000 0.000000 6.420000 ( 6.419870)
Each 5.830000 0.000000 5.830000 ( 5.829911)
Ruby 1.8.6 (Slower Machine)
user system total real
For 17.360000 0.000000 17.360000 ( 17.409992)
Each 21.130000 0.000000 21.130000 ( 21.250754)
Benchmarks 2
If you read the comment trail, there is a discussion about the speed of creating objects in for
vs each
. The link provided had the following benchmarks (although, I have cleaned up the formatting and fixed the syntax errors).
b = 1..10e5
Benchmark.bmbm (10) do |x|
x.report "each {}" do
b.each { |r| r + 1 }
end
x.report "each do end" do
b.each do |r|
r + 1
end
end
x.report "for do end" do
for r in b do
r + 1
end
end
end
Ruby 2.0
user system total real
each {} 0.150000 0.000000 0.150000 ( 0.144643)
each do end 0.140000 0.000000 0.140000 ( 0.143244)
for do end 0.150000 0.000000 0.150000 ( 0.147112)
Ruby 1.8.6
user system total real
each {} 0.840000 0.000000 0.840000 ( 0.851634)
each do end 0.730000 0.000000 0.730000 ( 0.732737)
for do end 0.650000 0.000000 0.650000 ( 0.647186)

- 9,044
- 4
- 37
- 74
-
1I understand this. I also know that internally Ruby converts for to each. But I wonder if there is still any case when for would be used instead of each. – p0deje Nov 25 '13 at 17:48
-
I found that when performance is an issue the `for` loop can be beneficial. Creating objects in Ruby is expensive and can cause an performance hit in loop with many iterations. – thomthom Nov 25 '13 at 17:57
-
@thomthom Can you provide benchmarks which show that this is the case? – Dan Grahn Nov 25 '13 at 17:58
-
@p0deje as explained in the answer it is only useful when you don't want the variable defined in the loop to be limited to the scope of the loop, which you can completely almost always avoid – bjhaid Nov 25 '13 at 18:03
-
@p0deje After thinking, I added an example of when it would be useful to use. – Dan Grahn Nov 25 '13 at 18:06
-
@screenmutt From this thread: http://sketchucation.com/forums/viewtopic.php?f=180&t=25305#p221022 referring to this link http://blog.shingara.fr/each-vs-for.html – thomthom Nov 25 '13 at 18:07
-
Note that SketchUp has been using Ruby 1.8 and the performance results might be different in newer versions. – thomthom Nov 25 '13 at 18:08
-
1@thomthom I just added the benchmarks. It does look like Ruby 1.8 has a faster run time for `for` loops, but that has been fixed. – Dan Grahn Nov 25 '13 at 18:21
-
Ah - yea, that matches what I just tested as well. Things have been turned around. – thomthom Nov 25 '13 at 18:25
I have written a few plugins for SketchUp's Ruby API and I found that when iterating large collections (of geometry entities) I would get better performance with a for in
loop over an each
block.
I believe this to be because the for in
loop doesn't create it's local scope and objects are reused instead of being created for every iteration as it would in the each
loop.
EDIT: The speed gain depends on Ruby version. Using the test snippet used in this article http://blog.shingara.fr/each-vs-for.html:
Ruby 1.8.6:
user system total real
For 14.742000 0.000000 14.742000 ( 14.777000)
Each 18.190000 0.000000 18.190000 ( 18.194000)
Ruby 2.0.0
user system total real
For 5.975000 0.000000 5.975000 ( 5.990000)
Each 5.444000 0.000000 5.444000 ( 5.438000)
Things has greatly improved since the old 1.8.6. (Though, SketchUp extension developers still need to optimize against this version.)

- 2,854
- 1
- 23
- 53
-
21.8.6 fell off supported status a long time ago. It was also a great deal slower, so its use for a comparison is dubious. Perhaps the final version of 1.8.7 would be more reasonable, but 1.9.3 would make more sense. – the Tin Man Nov 25 '13 at 20:03
-
1True, if you had control over the Ruby platform. But if you write extensions for SketchUp you have to deal with Ruby 1.8.6. – thomthom Nov 26 '13 at 10:43