=begin
module Enumerable
def map(&block)
o = self.class.new
each do |e|
o << yield(e)
end
o
end
end
But that breaks a lot of useful stuff. e.g.
a = File.open("/etc/passwd") { |f| f.map { |line| line.split(':') } }
or
str = File.read("/etc/passwd")
a = str.map { |line| line.split(':') }
That is: the contract for map is to run through an Enumerable and build the
results into an Array. It is not intended to run through an Enumerable and
to append the results into a new instance of whatever class that object
originally was.
It may not even be possible to create a new instance of that class, if the
initialize method requires arguments.
Aside: I suppose you could have such a pattern if you explicitly provided
the object to append to.
module Enumerable
def into(target=[], &blk)
blk ||= lambda { |e| e }
each { |e| target << blk[e] }
target
end
end
src = "one\ntwo\nthree\n"
p src.into([])
p src.into("") { |e| "*#{e}" }
src.into($stdout) { |e| e.upcase } # process a line at a time
data = ["one\n", "two\n", "three\n"]
p data.into("")
Perhaps even map itself could take the thing to write 'into' as an argument.
You could also argue that Hash#update should accept any Enumerable as its
argument, so you could write
a = [[1,:one], [2,:two], [3,:three]]
h = {}.update(a)
to convert an associative array to a hash.
But I've never needed either construct. Probably these things belong in the
Facets library, if not there already. There is value in minimising the
amount of magic in the core language, and there's a lot there already.
B.
=end