David Black:
I'm not sure about all this 'bad habit' and 'broken' stuff, but I do find it odd that #zip returns nil with a block.
Just for fun, here's an implementation:
module Z
def Z.included(c)
c.class_eval {
alias oldzip zip
def zip(*others,&block)
if block
res = []
newblock = Proc.new { |*args| res << block.call(*args) }
oldzip(*others,&newblock)
return res
else
oldzip(*others)
end
end
}
end
end
class Array; include Z; end
class Range; include Z; end
# and perhaps track down every Enumerable and do likewise....
(BTW, your 'reverse' example doesn't need the square brackets around i.reverse. Each element will already be an array.)
Fixed the reverse
example. Thanks David.
I made another implementation (didn't use each). Buts thats not of interest [>rubytalk:97006]. Lacks time to do a nice implementation with enumerator/callcc.. maybe when I get really tired I do that ;-)
BTW: I cannot seem to get links working inside this RCR comment.
-- Simon Strandgaard
Just looked at the source code and I think your proposal would lead to unnecessary array creation in case you don't need one.
If you need an Array, you can type 4 letters extra: a.zip(b).map {...} => [...]
It's the same like #each returning self.
Although I'm not a native speaker, I don't think, zip is semantically demanding an array as return value.
Could you explain, how enumerator can be used, I have no idea ?
-- Matthias Georgi
enumerator can be used to convert from one type of each to another. continuations can be used to restart the program. Together they can be used for multiway each.
I have made an iterator class, which is useful for multiway each. See >homepage.
require 'iterator'
data_a = %w(a b c d)
data_b = (0..3)
ia = Iterator::Continuation.new(data_a, :each)
ib = Iterator::Continuation.new(data_b, :each)
result = []
while ia.has_next? and ib.has_next?
result << ia.current
result << ib.current
ia.next
ib.next
end
ia.close
ib.close
p result # ["a", 0, "b", 1, "c", 2, "d", 3]
OK, looks like Generator, SyncEnumerator from stdlib. But I would only use them to pass Iterators around or to avoid recursion in combination with a stack. For general use it's too javalike, i was so confident not to type these "while next?" thing anymore. So probably it's personal taste, for me it's a good habit to write
[ 1, 2, 3 ].zip([ 10, 20, 30 ]).map {|i,j| i * j }
I use this very often and Iteration based on Continuation is also not very performant.
-- Matthias Georgi
Yes its java like.. it was just an example of how multiway each, over a one zillion of elements could be accomplished. People with such needs, should probably use C rather than using zip for this. Such demands is very specialized. I think zip rather should be targeted for the most common usage.
Have you ever felt wanting to supply a block to zip itself?
BTW: How do you convince a Perl girl to use Ruby, if you have to explain to her, that zip, is not zip in that paticular case, and you have to do a map afterwards!
-- Simon Strandgaard
OK, i see the inconsistency. I'm not sure, what i expect from zip. open() for example returns also different values, with and without a block.
-- Matthias Georgi
Great ;-)
Usually open
is some kind of factory method, and factories can build many kinds of products. zip
is not really in that category.
For instance map
returns the same as if you had supplied a simple block. The same would be nice with zip
.
server> irb
irb(main):001:0> a = %w(a b c)
=> ["a", "b", "c"]
irb(main):002:0> a.map
=> ["a", "b", "c"]
irb(main):003:0> a.map{|i| i}
=> ["a", "b", "c"]
irb(main):004:0> a.zip
=> [ ["a"], ["b"], ["c"] ]
irb(main):005:0> a.zip{|i| i}
=> nil ## [ ["a"], ["b"], ["c"] ] is what this RCR is about.
irb(main):006:0>
The last line is what this RCR is about.
-- Simon Strandgaard
David Black:
I'm not sure about all this 'bad habit' and 'broken' stuff, but I do find it odd that #zip returns nil with a block.
Just for fun, here's an implementation:
(BTW, your 'reverse' example doesn't need the square brackets around i.reverse. Each element will already be an array.)
Fixed the
reverse
example. Thanks David.I made another implementation (didn't use each). Buts thats not of interest [>rubytalk:97006]. Lacks time to do a nice implementation with enumerator/callcc.. maybe when I get really tired I do that ;-)
BTW: I cannot seem to get links working inside this RCR comment.
-- Simon Strandgaard
Just looked at the source code and I think your proposal would lead to unnecessary array creation in case you don't need one.
If you need an Array, you can type 4 letters extra: a.zip(b).map {...} => [...]
It's the same like #each returning self.
Although I'm not a native speaker, I don't think, zip is semantically demanding an array as return value.
Could you explain, how enumerator can be used, I have no idea ?
-- Matthias Georgi
enumerator can be used to convert from one type of each to another. continuations can be used to restart the program. Together they can be used for multiway each.
I have made an iterator class, which is useful for multiway each. See >homepage.
OK, looks like Generator, SyncEnumerator from stdlib. But I would only use them to pass Iterators around or to avoid recursion in combination with a stack. For general use it's too javalike, i was so confident not to type these "while next?" thing anymore. So probably it's personal taste, for me it's a good habit to write
I use this very often and Iteration based on Continuation is also not very performant.
-- Matthias Georgi
Yes its java like.. it was just an example of how multiway each, over a one zillion of elements could be accomplished. People with such needs, should probably use C rather than using zip for this. Such demands is very specialized. I think zip rather should be targeted for the most common usage.
Have you ever felt wanting to supply a block to zip itself?
BTW: How do you convince a Perl girl to use Ruby, if you have to explain to her, that zip, is not zip in that paticular case, and you have to do a map afterwards!
-- Simon Strandgaard
OK, i see the inconsistency. I'm not sure, what i expect from zip. open() for example returns also different values, with and without a block.
-- Matthias Georgi
Great ;-)
Usually
open
is some kind of factory method, and factories can build many kinds of products.zip
is not really in that category.For instance
map
returns the same as if you had supplied a simple block. The same would be nice withzip
.The last line is what this RCR is about.
-- Simon Strandgaard