Can't include a module in Enumerable?

T

Trans

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

Rick DeNatale

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

Gregory Brown

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
 
P

Pit Capitain

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

class Module
alias :eek: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
 
R

Robert Dober

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
 
T

Trans

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

class Module
alias :eek: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.
 
P

Pit Capitain

2007/6/24 said:
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
 
T

Trans

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,149
Members
46,695
Latest member
StanleyDri

Latest Threads

Top