On 2002-11-15 21:37:46 +0900, dblack / candle.superlink.net wrote:
> No, I mean the actual return value of the method call, which is a
> separate matter from the block.  In your example, if there were no
> block, the return value would be different.  In other words, given:
> 
>   n = [a,b,c].zip
>   m = [a,b,c].zip { |x,y,z| x*y+z }
> 
> n and m would not be the same.  That's where I'm scratching my head
> and wondering if that's the best way.

The first case is equivalent to the second case with the block
{ |*tuple| tuple }. If no block is given, zip just uses the array of
parameters of this block.

In fact that's exacly the way I implemented zip and unzip while
converting some Haskell functions into Ruby. Haskell has zip, zip3,
zipWith and zipWith3 and all of this functions can be replaced by a
single Ruby method which even can do zipWithN:

module Enumerable

	def zip(&block)
		block ||= lambda { |*tuple| tuple }
		size = nil
		map { |x| x.size }.each do |s|
			size ||= s
			s == size or raise "zip with unequal length lists"
		end
		result = []
		i = 0
		catch(:stop) do
			tuple = []
			each do |l|
				l[i] or throw :stop
				tuple << l[i]
			end
			result << block.call(*tuple)
			i += 1
			redo
		end
		result
	end

	def unzip(&block)
		block ||= lambda { |*tuple| tuple }
		result = []
		size = nil
		each do |x|
			tuple = block.call(*x)
			i = 0
			size ||= tuple.size
			size == tuple.size or raise "unzip with unequal length pairs"
			tuple.each do |t|
				(result[i] ||= []) << t
				i += 1
			end
		end
		result
	end

end

To implement this in C is unfortunately a bit more difficult, I fear.

-- 
Programs must be written for people to read, and only incidentally for 
machines to execute.
  -- Abelson/Sussman, "The Structure and Interpretation of Computer Programs"