On Thu, Nov 4, 2010 at 9:45 AM, Klaus Stein <usenet / istik.de> wrote:
> Intransition <transfire / gmail.com> wrote:
>>
>> Mixins are just another way to do inheritance. It has the same issues.
>> The only difference is the module level --and that's just an arbitrary
>> deviation often circumvented by "ClassMethods" hacks..
>>
> What I would like to have are Mixins (especially Enumerable) behaving some
> more clever.
>
> Asume I have some MyCollection class. I implement #each and include
> Enumerable. Now I can do:
>
> mc = MyCollection.new('some', 'data', 'here', 'and', 'there')
> mc4 = mc.select { |s| s.length != 4 }
>
> But, unfortunately, mc4.class is Array and not MyCollection. I have to
> implement select, reject and others by myself, loosing some of the nice help
> Enumerable gives me.
>
> I often want to chain things and call some mapping method on some collection
> class without falling back to Array.
>
> This could be solved if Enumerable looks for some MyCollection.newEnum()
> class method and calls it if present to create a new object for collecting
> the results of the select (or some other mechanism, not sure how to go
> best. Any way to tell Enumerable how to collect the results of the mapping
> method in a new MyCollection object will do).

Of course there are ways that could be used to implement what you want, e.g.

module Enumerable
  # default: new behavior
  def select_2(cl = self.class)
    r = (cl.new rescue [])
    each {|x| r << x if yield x}
    r
  end
end

But this does not solve the major issue that you change the interface.
 Currently there is a ton of code around that works with the
assumption (explicit or implicit) that #select returns an Array.  I
would not dare judge how much code will be broken if we change the
default behavior.

A solution would be this:

module Enumerable
  # default: old behavior
  def select_2(cl = Array)
    r = cl.new
    each {|x| r << x if yield x}
    r
  end
end

But then you loose the convenience to not have to provide the type.

Kind regards

robert



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