Gordon Miller (gmiller / promisemark.com) wrote:
> Doing numerically oriented algorithms I find myself frequently doing 
> something like the following:
> 
> z = (1..5).to_a
> a = (0..5).to_a
> b = (0..5).to_a
> c = z.collect_with_index { |el, i| f(el, a[i], b[i]) }
> 
> something along the lines of a zip...
> 
> c = zip (z, a, b).collect { |el| f(el[0], el[1], el[2]) }

I'm also always amazed by the uses of inject.  The collect_with_index
could be done:

  c = z.inject( [] ) { |arr, el| 
        arr << f( el, a[arr.length], b[arr.length] ) 
      }

Actually, I think an each_with_index equivalent is kinda neat
with inject, as you can explicitly set the first index:

  arr = []
  z.inject( 0 ) { |i, el|
    arr[i] = f(el, a[i], b[i])
    i + 1
  }

It would be really cool if, instead of having a million *_with_index
methods floating around in Enumerable, we had a method which could be
used inside a block to retrieve the number of iterations that the block
has undergone.

For instance:

  class Array
    def collect( &e )
      ary = []
      i = 0
      self.each { |item|
        eval( "def index; #{i} end", e )
        ary.push( e.call( item ) )
        i += 1
      }
      return ary
    end
  end

The `index' method can then be used in the block:

  c = z.collect { |el| f(el, a[index], b[index]) }

This implementation is flawed, though, because it creates the `index'
method in whatever namespace the block is originally placed.  But, you
know.. what if?? 

_why