# Can't include a module in Enumerable?

Discussion in 'Ruby' started by Trans, Jun 23, 2007.

1. ### TransGuest

irb(main):002:1> module Z
irb(main):003:1> def x; "x"; end
irb(main):004:1> end
=> nil
irb(main):005:0> module Enumerable
irb(main):006:1> include Z
irb(main):007:1> end
=> Enumerable
irb(main):008:0> a = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb(main):009:0> a.x
NoMethodError: undefined method `x' for [1, 2, 3, 4, 5]:Array
from (irb):9
from :0

Is the Double Inclusion Problem worse than I realized? I thought the
above would be okay b/c 'a' is instantiated _after_ the inclusion
(which is why I've often called it the Dynamic Inclusion Problem).
What gives?

T.

Trans, Jun 23, 2007

2. ### Rick DeNataleGuest

On 6/23/07, Trans <> wrote:
> irb(main):002:1> module Z
> irb(main):003:1> def x; "x"; end
> irb(main):004:1> end
> => nil
> irb(main):005:0> module Enumerable
> irb(main):006:1> include Z
> irb(main):007:1> end
> => Enumerable
> irb(main):008:0> a = [1,2,3,4,5]
> => [1, 2, 3, 4, 5]
> irb(main):009:0> a.x
> NoMethodError: undefined method `x' for [1, 2, 3, 4, 5]:Array
> from (irb):9
> from :0
>
> Is the Double Inclusion Problem worse than I realized? I thought the
> above would be okay b/c 'a' is instantiated _after_ the inclusion
> (which is why I've often called it the Dynamic Inclusion Problem).
> What gives?

It's not the instance, it's the class Array, and that existed (and
included Enumerable) before you changed Enumerable.

--
Rick DeNatale

My blog on Ruby

Rick DeNatale, Jun 23, 2007

3. ### Gregory BrownGuest

On 6/23/07, Trans <> wrote:
> irb(main):002:1> module Z
> irb(main):003:1> def x; "x"; end
> irb(main):004:1> end
> => nil
> irb(main):005:0> module Enumerable
> irb(main):006:1> include Z
> irb(main):007:1> end
> => Enumerable
> irb(main):008:0> a = [1,2,3,4,5]
> => [1, 2, 3, 4, 5]
> irb(main):009:0> a.x
> NoMethodError: undefined method `x' for [1, 2, 3, 4, 5]:Array
> from (irb):9
> from :0
>
> Is the Double Inclusion Problem worse than I realized? I thought the
> above would be okay b/c 'a' is instantiated _after_ the inclusion
> (which is why I've often called it the Dynamic Inclusion Problem).
> What gives?

Rick answered this, but maybe this is a solution for what you're trying to do:

>> module ZEnumerable
>> include Enumerable
>> def x; "x"; end
>> end

>> class B
>> include ZEnumerable
>>

?> def each
>> [1,2,3].each { |e| yield(e) }
>> end
>> end

>> class Array
>> include ZEnumerable
>> end

=> Array
>> [1,2,3].x

=> "x"
>> B.new.map { |e| e + 1 }

=> [2, 3, 4]
>> B.new.x

=> "x"

Yeah, you'd need to go remix existing enumerable classes, but it keeps
you from having to do the additional include for *new* objects

Gregory Brown, Jun 23, 2007
4. ### Pit CapitainGuest

Tom, here's something to experiment with. I haven't tested it extensively:

class Module
alias ld_include :include
def include other
old_include other
if self.class == Module
this = self
ObjectSpace.each_object Module do |mod|
mod.module_eval do include this end if mod < self
end
end
end
end

module Z
def x; "x"; end
end

module Enumerable
include Z
end

a = [1,2,3,4,5]
p a.x # => "x"

Regards,
Pit

Pit Capitain, Jun 24, 2007
5. ### Robert DoberGuest

On 6/23/07, Trans <> wrote:
> irb(main):002:1> module Z
> irb(main):003:1> def x; "x"; end
> irb(main):004:1> end
> => nil
> irb(main):005:0> module Enumerable
> irb(main):006:1> include Z
> irb(main):007:1> end
> => Enumerable
> irb(main):008:0> a = [1,2,3,4,5]
> => [1, 2, 3, 4, 5]
> irb(main):009:0> a.x
> NoMethodError: undefined method `x' for [1, 2, 3, 4, 5]:Array
> from (irb):9
> from :0
>
> Is the Double Inclusion Problem worse than I realized? I thought the
> above would be okay b/c 'a' is instantiated _after_ the inclusion
> (which is why I've often called it the Dynamic Inclusion Problem).
> What gives?
>
> T.
>
>

Just reinclude Enumerable, well that seems to be the simplest way to
achieve what you wanted:
>

510/10 > irb
irb(main):001:0> module A; def x; 42 end end
=> nil
irb(main):002:0> module Enumerable; include A end
=> Enumerable
irb(main):003:0> class Array; include Enumerable end
=> Array
irb(main):004:0> [].x
=> 42

And yes it works outside irb too.

Robert
--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

Robert Dober, Jun 24, 2007
6. ### TransGuest

On Jun 24, 4:37 am, "Pit Capitain" <> wrote:
> Tom, here's something to experiment with. I haven't tested it extensively:
>
> class Module
> alias ld_include :include
> def include other
> old_include other
> if self.class == Module
> this = self
> ObjectSpace.each_object Module do |mod|
> mod.module_eval do include this end if mod < self
> end
> end
> end
> end
>
> module Z
> def x; "x"; end
> end
>
> module Enumerable
> include Z
> end
>
> a = [1,2,3,4,5]
> p a.x # => "x"
>
> Regards,
> Pit

Pit Smack Down! You go and solve the Double Inclusion Problem just
like that!?

There must be a large issue. Why wouldn't Matz have already pursued
this? Granted, I see a little inefficiency, but nothing an Observer
pattern couldn't mitigate. What say you?

I'm Speechless.

T.

Trans, Jun 24, 2007
7. ### Pit CapitainGuest

2007/6/24, Trans <>:
> Pit Smack Down! You go and solve the Double Inclusion Problem just
> like that!?
>
> There must be a large issue. Why wouldn't Matz have already pursued
> this? Granted, I see a little inefficiency, but nothing an Observer
> pattern couldn't mitigate. What say you?
>
> I'm Speechless.

Tom, thanks for the kind words, but it's really not so hard to find
just one solution to this problem. I can't speak for Matz, but I think
he's looking for a more efficient solution that doesn't require a lot
of bookkeeping.

Regards,
Pit

Pit Capitain, Jun 24, 2007
8. ### TransGuest

On Jun 24, 8:01 am, "Pit Capitain" <> wrote:
> 2007/6/24, Trans <>:
>
> > Pit Smack Down! You go and solve the Double Inclusion Problem just
> > like that!?

>
> > There must be a large issue. Why wouldn't Matz have already pursued
> > this? Granted, I see a little inefficiency, but nothing an Observer
> > pattern couldn't mitigate. What say you?

>
> > I'm Speechless.

>
> Tom, thanks for the kind words, but it's really not so hard to find
> just one solution to this problem. I can't speak for Matz, but I think
> he's looking for a more efficient solution that doesn't require a lot
> of bookkeeping.

Okay, I'm being a bit hyperbolic. But you deserve it anyway. I was
surprised to see a solution thrown up in a few lines of code. The
impression I had developed over previous discourse was such a thing
was not readily possible. Of course, now it seems obvious. I knew we
could just re-include the module, I just never put two and two
together.

T.

Trans, Jun 24, 2007