Martin DeMello <martindemello / yahoo.com> wrote:

> ibotty <me / ibotty.net> wrote:
> > 
> >> Not quite, but for parallel traversing made easier
> >> 
> >> a.zip(b).map {|i, j| i*j}
> > 
> > this is indeed much more elegant.
> > 
> > but because array * array is not defined, me thinks. one could implement
> > (this simple case) this way.

In APL, * and other operators work like this, element-by-element.

> Here's a handy generalisation of the method:
> 
> class Array
>   def mapwith(*args, &block)
>     if block_given?
>       zip(*args).collect {|i, j| yield i, j}
>     else
>       f = args.pop
>       zip(*args).collect {|i, j| i.send(f, j)}
>     end
>   end
> end
> 
> p [1,2,3].mapwith([4,5,6]) {|i,j| i*j}
> p [1,2,3].mapwith([4,5,6], :*) 

Should #mapwith work with 3 or more arrays like #zip does?

  p [1,2,3].mapwith([4,5,6], [7,8,9]) {|i,j,k| i*j+k}

Allowing #zip to take a block has been discussed before.  Here's yet
another implementation:

  class Array
    alias _zip zip
    def zip(*args)
      if block_given?
        _zip(*args).map {|a| yield a}
      else
        _zip(*args)
      end
    end
  end

  p [1,2,3].zip([4,5,6], [7,8,9]) {|i,j,k| i*j+k}

Unfortunately, it doesn't allow taking a symbol to an operator (:*)
like #mapwith does.