For or each?

I just used the new roodi gem to check out some of my code that has a
lot of algorithmic code. It gave me a number of issues with the
phrase "Don't use 'for' loops. Use Enumerable.each instead." I prefer
for loops as opposed to using each simply because it's what I'm used
to coming from C-style languages.

Example:

This is what I do:

  for i in 0...str.size
    ...
  end

This is what roodi would have me do

  (0...str.size).each do |i|
    ...
  end

Is there a real, substantive reason to use each instead of for? Or is
it simply just a preference issue?

Thanks,

···

--
     TekWiz

tekwiz wrote:

This is what roodi would have me do

  (0...str.size).each do |i|
    ...
  end

Is there a real, substantive reason to use each instead of for? Or is
it simply just a preference issue?

It leaves you closer to a refactor to .map or .inject or .select or .reject or .delete_if or .each_index or .each_with_index or ...

···

--
   Phlip
   O'Reilly Media - Technology and Business Training

It's interesting that array access using 'each' seems to be much faster on my machine. In C, indexed-based for-loops are slow. It's faster to increment pointers. Maybe it's similar under Ruby's hood.

ruby 1.86 (OS X PPC)
Rehearsal --------------------------------------------------
for loop 1.200000 0.000000 1.200000 ( 1.206533)
each 0.510000 0.000000 0.510000 ( 0.511994)
----------------------------------------- total: 1.710000sec

                      user system total real
for loop 1.190000 0.000000 1.190000 ( 1.190023)
each 0.500000 0.000000 0.500000 ( 0.508636)

ruby 1.9 (Same OS X PPC)
Rehearsal --------------------------------------------------
for loop 2.370000 0.010000 2.380000 ( 2.376402)
each 1.770000 0.000000 1.770000 ( 1.775798)
----------------------------------------- total: 4.150000sec

                      user system total real
for loop 2.310000 0.010000 2.320000 ( 2.316495)
each 1.780000 0.000000 1.780000 ( 1.775958)

Joe

···

On 20 sept. 08, at 15:50, tekwiz wrote:

I just used the new roodi gem to check out some of my code that has a
lot of algorithmic code. It gave me a number of issues with the
phrase "Don't use 'for' loops. Use Enumerable.each instead." I prefer
for loops as opposed to using each simply because it's what I'm used
to coming from C-style languages.

Example:

This is what I do:

  for i in 0...str.size
    ...
  end

This is what roodi would have me do

  (0...str.size).each do |i|
    ...
  end

Is there a real, substantive reason to use each instead of for? Or is
it simply just a preference issue?

Thanks,
--
     TekWiz

You should look at the Matz book The Ruby Programming Language page 137:

external or internal iterators

···

On Sep 20, 2008, at 9:50 PM, tekwiz wrote:

I just used the new roodi gem to check out some of my code that has a
lot of algorithmic code. It gave me a number of issues with the
phrase "Don't use 'for' loops. Use Enumerable.each instead." I prefer
for loops as opposed to using each simply because it's what I'm used
to coming from C-style languages.

Example:

This is what I do:

  for i in 0...str.size
    ...
  end

This is what roodi would have me do

  (0...str.size).each do |i|
    ...
  end

Is there a real, substantive reason to use each instead of for? Or is
it simply just a preference issue?

Thanks,
--
     TekWiz

Phlip wrote:

tekwiz wrote:

This is what roodi would have me do

  (0...str.size).each do |i|

It leaves you closer to a refactor to .map or .inject or .select or .reject or .delete_if or .each_index or .each_with_index or ...

It also hints at:

   str.each do |ch|

...

Phlip wrote:

str.each do |ch|

That'd be each_char, I suppose. String#each is each_line.

···

--
Jabber: sepp2k@jabber.org
ICQ: 205544826

So, it's a code-readability issue and not a functional or complexity
issue?

···

On Sep 20, 3:32 pm, Phlip <phlip2...@gmail.com> wrote:

Phlip wrote:
> tekwiz wrote:

>> This is what roodi would have me do

>> (0...str.size).each do |i|
> It leaves you closer to a refactor to .map or .inject or .select or
> .reject or .delete_if or .each_index or .each_with_index or ...

It also hints at:

str.each do |ch|

--
    TekWiz

Joe Wölfel wrote:

It's interesting that array access using 'each' seems to be much faster on my machine.

Does 'for' reevaluate its range after each tick? That would give 'for' a single technical advantage over .each, in the very rare chance you need that.

Otherwise, where does the time go?

A quick experiment with RubyNode just showed Ruby generates different opcodes for 'each' and 'for'. (By contrast, the notorious ternary operator, ? :, generates the same opcodes as an equivalent 'if then else end' construction.)

···

--
   Phlip

Actually for loops are faster than `each`. Since it doesn't
introduce a block, there's no extra scope created. Not much faster,
but they are used in the computer language shootout, for instance.

You folks can argue all you want about the look of the `for` but
you're forgetting the utility of having two nice choices. One which
creates scope and one that doesn't. Don't let this Roodi lib boss
you around! You can make up your own mind about things.

_why

···

On Sun, Sep 21, 2008 at 07:04:49AM +0900, Joe Wölfel wrote:

It's interesting that array access using 'each' seems to be much faster on
my machine. In C, indexed-based for-loops are slow. It's faster to
increment pointers. Maybe it's similar under Ruby's hood.

str.each do |ch|

That'd be each_char, I suppose. String#each is each_line.

IOW:

  ... or .each_char or .each_line or .each_byte or ...

tekwiz wrote:

It leaves you closer to a refactor to .map or .inject or .select or
.reject or .delete_if or .each_index or .each_with_index or ...

So, it's a code-readability issue and not a functional or complexity
issue?

'for' is arguably more readable. And it's not a performance issue - I suspect the opcodes will be the same. It is very much a technical issue.

Good code is readable, minimal, and maintainable. Maintaining code requires
adding new features. Code should always be as ready for change as possible, so
much of our design rules (such as "object orientation") are really rubrics for
improving the odds that the next change comes easy.

This is an easier change...

   array.each{|x| ... } -> array.map{|x| ... }

...than this:

   for x in array ... -> array.map{|x| ... }

Further, your original example was very C-like. The iteration variable was the
array's index. Most iteration directly addresses each array's element, without
regard to its index. So 'for i in 0...str.size' is often more excessive than
'for x in str'.

Using .each leads to the correct mindset. Put another way, 'for' is an obsolete
concept - a legacy of languages without true iteration.

···

--
   Phlip

You can try my test if you like. I haven't checked it carefully. But it does seem like 'each' is much faster under both ruby 1.86 and ruby 1.9. The code is below.

require 'rubygems'
require 'benchmark'

a = (1..10000).to_a
Benchmark.bmbm 15 do |bench|

  bench.report "for loop" do
    x = 0
    100.times do
      for i in 0...(a.size)
        x += a[i]
      end
    end
  end
  
   bench.report "each" do
    x = 0
    100.times do
      a.each do |i|
        x += i
      end
    end
  end
  
end

Joe

···

On 20 sept. 08, at 18:17, Phlip wrote:

Joe Wölfel wrote:

It's interesting that array access using 'each' seems to be much faster on my machine.

Does 'for' reevaluate its range after each tick? That would give 'for' a single technical advantage over .each, in the very rare chance you need that.

Otherwise, where does the time go?

A quick experiment with RubyNode just showed Ruby generates different opcodes for 'each' and 'for'. (By contrast, the notorious ternary operator, ? :, generates the same opcodes as an equivalent 'if then else end' construction.)

--
  Phlip

These things are not entirely separate -- readable code is more likely to be
functional and maintainable.

Or, maybe a better way of saying it is, the code should not merely be
readable, it should be expressing your intent.

Each is far more abstract than for. Take a simple array:

a = ['one','two','three']
for i in 0...a.size
  puts "Give me a #{a[i]}"
end

That's more prone to not work, as there are more visible moving parts, which
means more for you to think about, and more that can go wrong -- you might
type the wrong variable name in the a[i], for example, or type 0..a.size
instead of 0...a.size.

It also doesn't express your intent. You don't really need to know or care
where you are in that array, in this particular algorithm. You only need to
know which item you're going to print right now. So:

['one','two','three'].each do |x|
  puts "Give me a #{x}"
end

Shorter, more readable (to me), quicker to type, and has the added benefit
that in the above example, that array falls out of scope as soon as the loop
ends, so it can be collected sooner.

It also gives you a bit more flexibility. Suppose you're iterating over
something that someone passed in -- that means that I have to pass in
something that behaves like an array. It needs to have an accurate method,
probably supporting random access, even if you'll only access it
sequentially. It needs to have a length method, etc.

Which makes things quite a bit more awkward. What if I'm reading lines from a
file? Your way would force me to count every line in the file before I even
get started. What if it's a complex computation, like all the primes less
than a given number? I have to calculate them all out ahead of time, and
either store that array (wasting memory), or recalculate them from the
beginning.

There's more to it, of course -- you could imagine an each method which runs
in parallel threads, and I'm sure someone has written such a thing.

None of these will apply to every situation. It's entirely possible it's an
internal data structure. Even internal data structures could benefit from
some flexibility, but maybe you'll never touch this algorithm again.

But then, I don't really see a downside to doing it with 'each', instead
of 'for', other than that 'for' is what you're used to.

···

On Saturday 20 September 2008 16:07:20 tekwiz wrote:

On Sep 20, 3:32 pm, Phlip <phlip2...@gmail.com> wrote:
> Phlip wrote:
> > tekwiz wrote:
>
> >> This is what roodi would have me do
>
> >> (0...str.size).each do |i|
> > It leaves you closer to a refactor to .map or .inject or .select or
> > .reject or .delete_if or .each_index or .each_with_index or ...
>
> It also hints at:
>
> str.each do |ch|

So, it's a code-readability issue and not a functional or complexity
issue?

_why wrote:

You folks can argue all you want about the look of the `for` but
you're forgetting the utility of having two nice choices.

Tx that's why I said 'for' can be more readable - even though I know nobody in person aware of its existence.

> One which

creates scope and one that doesn't. Don't let this Roodi lib boss
you around! You can make up your own mind about things.

Classic 'lint' comes with switches to STFU some warnings, thus making others more useful...

···

--
   Phlip

Any thoughts on the Ruby 1.9 result? It seems like 'each' is much faster than either the original for loop we started talking about, or the non-index based one (for loop 2). You can run the code below if you like.

Ruby 1.9 output:
Rehearsal --------------------------------------------------
for loop 1.240000 0.000000 1.240000 ( 1.240751)
for loop 2 1.180000 0.000000 1.180000 ( 1.176560)
each 0.510000 0.010000 0.520000 ( 0.512496)
----------------------------------------- total: 2.940000sec

                      user system total real
for loop 1.190000 0.010000 1.200000 ( 1.197695)
for loop 2 1.180000 0.000000 1.180000 ( 1.177620)
each 0.510000 0.000000 0.510000 ( 0.508858)

Ruby 1.86 output:
Rehearsal --------------------------------------------------
for loop 2.840000 0.040000 2.880000 ( 2.880437)
for loop 2 1.660000 0.000000 1.660000 ( 1.661229)
each 1.750000 0.010000 1.760000 ( 1.755502)
----------------------------------------- total: 6.300000sec

                      user system total real
for loop 2.300000 0.000000 2.300000 ( 2.307566)
for loop 2 1.660000 0.010000 1.670000 ( 1.666218)
each 1.760000 0.000000 1.760000 ( 1.760356)

require 'rubygems'
require 'benchmark'

a = (1..10000).to_a
Benchmark.bmbm 15 do |bench|

  bench.report "for loop" do
    x = 0
    100.times do
      for i in 0...(a.size)
        x += a[i]
      end
    end
  end

  bench.report "for loop 2" do
    x = 0
    100.times do
      for i in a
        x += i
      end
    end
  end
  
   bench.report "each" do
    x = 0
    100.times do
      a.each do |i|
        x += i
      end
    end
  end
end

···

On 20 sept. 08, at 20:10, _why wrote:

Actually for loops are faster than `each`. Since it doesn't
introduce a block, there's no extra scope created. Not much faster,
but they are used in the computer language shootout, for instance.
_why

No:

class Numeric
   def foo
      puts "foo"
      self
   end
end
for i in 1..10.foo
   puts i
end

prints:

foo
1
2
3
4
5
6
7
8
9
10
=> 1..10

···

Phlip <phlip2005@gmail.com> wrote:

Joe Wölfel wrote:

It's interesting that array access using 'each' seems to be much
faster on my machine.

Does 'for' reevaluate its range after each tick? That would give
'for' a single technical advantage over .each, in the very rare
chance you need that.

--
Chanoch (Ken) Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/

Phlip wrote:

> That'd be each_char, I suppose. String#each is each_line.

IOW:

... or .each_char or .each_line or .each_byte or ...

What?

Confused,
Sebastian

···

--
Jabber: sepp2k@jabber.org
ICQ: 205544826

I don't think the minimal editing distance between #each and #map and
friends has anything to do. It is so unlikely that an #each becomes an
#inject that I don't think that's a good explanation for why people
prefer it over for. If <<some code>> becomes an #inject you just go an
edit whatever you need. Nah I don't think so.

The analogous for loop is written like this

   for item in collection
     # do something with item
   end

I think #each has become the common for-idiom in Ruby because, you
know, the community has converged to that choice by themselves. That's
not very tangible, and perhaps may be due to the fact that blocks are
ubiquitous in Ruby and #each is syntactically closer in your head to a
lot of other stuff in Ruby.

I'd say #each is not that much favoured in ERb templates.

Hey that's not the for-version of #each, nobody iterates by index in
dynamic languages unless he needs to.

The message to the OP is: for versus each is a stylistic discussion in
the sense that they are equivalent *if used the way I showed*. A
regular loop over a collection using indexes is never used in dynamic
languages because it is much slower than array indexing in C. That's
the price you pay for such flexible estructures. In Ruby an array has
nothing to do behind the scenes with a C array.

That's why VHLLs provide specific efficient and concise collection iterators:

   # Perl
   foreach my $user (@users) {
       ...
   }

   # Ruby
   for user in users
     ...
   end

   # or

   users.each do |user|
     ...
   end

   # Python
   for user in users
       ...

   # Lisp
   (dolist (user users)
     (...))

···

On Sun, Sep 21, 2008 at 12:26 AM, Joe Wölfel <joe@talkhouse.com> wrote:

                       for i in 0...(a.size)
                               x += a[i]
                       end

Joe Wölfel wrote:

You can try my test if you like. I haven't checked it carefully. But it does seem like 'each' is much faster under both ruby 1.86 and ruby 1.9. The code is below.

I just experimented with 'for' and found it does not reevaluate its header each time it runs. That's the only thing that could have explained the time difference, so maybe Matz & Co. have simply neglected 'for' while optimizing .each, which everyone uses. (Though it's still technically superior; not just an /ad populum/ thing...)

Another reason to use .each is your collection-like class might override it to do something cool...