Sylvain J. wrote:
Nope. each { } needs one new scope for each iteration
By ‘scope’ do you mean ‘stack frame’?
Take this trivial example:
def each1
yield 1
yield 2
yield 3
end
each1 { :dummy }
The only ‘objects’ being created here are stack frames, by the yield
statements calling the block. To make it more explicit,
def each2(&blk)
blk.call(1)
blk.call(2)
blk.call(3)
end
each2 { :dummy }
Now, if you are arguing that the above code creates three objects which
need to be garbage-collected later, then you’re also arguing that the
sequence
foo(1)
foo(2)
foo(3)
creates three objects which need to be garbage-collected, and therefore
that the loop
for i in (1…3)
foo(i)
end
also creates three garbage objects.
I don’t believe that’s the case. I would imagine that the stack runs as,
well, a stack. (It’s not quite that simple when you get into creating
closures of course, but if you call a closure 1000 times, you’re not
creating 1000 new closures)
Am I missing something?
Finally, I tried some simple measurements.
$ time ruby -e ‘a = (1…5_000_000).to_a; a.each { :dummy }’
$ time ruby -e ‘a = (1…5_000_000).to_a; for i in a; :dummy; end’
Under ruby 1.8.6p114, I find the first is about 5% faster.
Under ruby 1.8.4 (Ubuntu Dapper), I find the first is about 25% faster.
This is on relatively old Pentium machines though.