>   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.