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"