Under ruby 1.8.6, running
[1, 2, 3].collect
results in an array of [1, 2, 3].
Huh. That's odd.
[1, 2, 3].collect
results in an Enumerator, which I then have to call .to_a on.
Given that the original is an array, you probably wouldn't actually do this.
Let's see...
I was just wondering if
anyone had any insight into why that change was made, because it feels
very counter intuitive to me.
I agree with Rick -- the basic idea here is that all enumerator methods will
turn into Enumerators when called without a block. I especially like doing it
with variants of each.
I really liked the elegance of opening
up a file and just calling collect to turn it into an array.
An array of what? I wouldn't call that elegant, I'd call that confusingly
magical. I think this is much easier to understand:
lines = open('foo') {|file| file.each_line.to_a}
Now I know exactly what's happening -- make an array of each line in the file.
You could argue that this should be the default, but if you just did 'each',
it's not obvious. I could, after all, be doing something like this:
chars = open('foo') {|file| file.each_char.to_a}
Or, if it's a binary file, something like this:
bytes = open('foo') {|file| file.each_byte.to_a}
You could also argue that the to_a should be unnecessary, but I don't agree.
For one, it's really very useful to have that kind of shorthand for an
Enumerator, for those few times it makes sense. For example:
open 'foo' do |file|
lines = file.each_line
begin
loop do
line = lines.next.chomp
while line =~ /\\$/
line = line.chop + lines.next.chomp
end
# do something with each continued line
end
rescue StopIteration
end
end
I'm sure I could come up with other examples, too, including silly ones like:
(1..10).each_cons(2).map{|a,b| a*b}
Basically, I'm trying to say that Enumerators are cool -- I can think of all
kinds of crazy uses for them, including one-liners like the above that rely on
this behavior. I can't really think of a good reason for them to return arrays
-- after all, you can always do a to_a at the end of a chain like that, if you
actually need an array.
And anyway, if it's just something that someone will be calling 'each' on at
some point, you probably don't need an array, and it's more efficient to use
an enumerator anyway. After all, here's another contrived example:
byte_pairs = open('foo') {|file| file.each_char.each_slice(2).to_a }
line_pairs = open('foo') {|file| file.each_line.each_slice(2).to_a }
Both would work if each_char/each_line made an array, but the above is much
more efficient.
···
On Saturday 05 December 2009 11:40:54 am Raul Jara wrote: