On Thu, Nov 4, 2010 at 10:55 AM, Klaus Stein <usenet / istik.de> wrote:
> Robert Klemme <shortcutter / googlemail.com> wrote:

>> But this does not solve the major issue that you change the interface.
>>  ¨Βυςςεξτμω τθεςισ τοοζ γοδε αςουξδ τθατ χοςλχιτθ τθ>> assumption (explicit or implicit) that #select returns an Array.  ¨Β
>> would not dare judge how much code will be broken if we change the
>> default behavior.
>
> This is why I would not want this as _default_ behavior. I would expect
> select, reject etc return an Array as it is now. But if the class including
> Enumerable provides a _special_ MyCollection::enumNew method it would be
> used instead.
>
> So something like
>
> module Enumerable
>  ¨Βεζ σεμεγτ
>  ¨Β ¨σεμζ®γμασσ®εξυνΞεχ¨σεμζςεσγυε Ϋέ>  [ rest of the select code ]
>  ¨Βξδ
> end
>
> would do. This should not break old code.

It will, because classes can be modified in Ruby.

require 'set'

class Set
  def self.enum_new(other_set)
    new
  end
end

require 'a_library_that_uses_set'

...

x = a_set.select {|x| x > 0}
assert { Array === x } # boom!

Again, global state (in this case a method in class Set) bytes.  My
suggested approach with providing the class as argument is better IMHO
because

- It is more flexible (at one time you can map an Array to a Set,
another time to an Array etc.).

- It does not break old code (see above).

Actually you do not want to determine the return type of Set#map
*globally* but rather per *use*.

> I am not sure how to implement this best, as creating an empty collection
> and adding elements by << ma be not the most efficient way to go.

There is no other way because you do not know beforehand whether all
or only part of the elements of the current collection go into the new
one.

> (please note that MyCollection.enumNew takes the original object as
>  ¨Βαςανετες το βε αβμε το γοπω οτθειξσταξγε φαςιαβμεετγ©

I noticed that but this is useless without knowing what the copy will
be used for.  Enumerable#map and #select have vastly differing
semantics!

Cheers

robert


-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/