[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Nested Mixin Problem(?

Vasco Andrade e silva

7/2/2007 1:51:00 AM

Hi,

could someone check and comment if this is something that i don't
understand well or a ruby "somehow" problem? please

Here's the code:

module A
def a; :a; end
end

module B
include A
def b; :b; end
end

module C
def c; :c; end
end

class D
include B
end

D.new.a #=> :a ## Ok for me
D.new.b #=> :b ## Ok for me

module B
include C
end

D.new.c #=> NoMethodError: undefined method `c' for #<D:0xb7cb985c> ##
This is not ok for me.

Thanks,
Vasco Andrade e Silva

--
Posted via http://www.ruby-....

7 Answers

Chris Shea

7/2/2007 2:40:00 AM

0

On Jul 1, 7:51 pm, Vasco Andrade e Silva <vasc...@gmail.com> wrote:
> Hi,
>
> could someone check and comment if this is something that i don't
> understand well or a ruby "somehow" problem? please
>
> Here's the code:
>
> module A
> def a; :a; end
> end
>
> module B
> include A
> def b; :b; end
> end
>
> module C
> def c; :c; end
> end
>
> class D
> include B
> end
>
> D.new.a #=> :a ## Ok for me
> D.new.b #=> :b ## Ok for me
>
> module B
> include C
> end
>
> D.new.c #=> NoMethodError: undefined method `c' for #<D:0xb7cb985c> ##
> This is not ok for me.
>
> Thanks,
> Vasco Andrade e Silva
>
> --
> Posted viahttp://www.ruby-....

Vasco,

My understanding of this is that you can imagine include just pasting
in the module code when its evaluated. So any changes to the module B
after the include won't be included in the class D, because the
copy&paste into the class has already happened.

HTH,
Chris

Chris Shea

7/2/2007 2:47:00 AM

0

On Jul 1, 8:40 pm, Chris Shea <cms...@gmail.com> wrote:
> On Jul 1, 7:51 pm, Vasco Andrade e Silva <vasc...@gmail.com> wrote:
>
>
>
> > Hi,
>
> > could someone check and comment if this is something that i don't
> > understand well or a ruby "somehow" problem? please
>
> > Here's the code:
>
> > module A
> > def a; :a; end
> > end
>
> > module B
> > include A
> > def b; :b; end
> > end
>
> > module C
> > def c; :c; end
> > end
>
> > class D
> > include B
> > end
>
> > D.new.a #=> :a ## Ok for me
> > D.new.b #=> :b ## Ok for me
>
> > module B
> > include C
> > end
>
> > D.new.c #=> NoMethodError: undefined method `c' for #<D:0xb7cb985c> ##
> > This is not ok for me.
>
> > Thanks,
> > Vasco Andrade e Silva
>
> > --
> > Posted viahttp://www.ruby-....
>
> Vasco,
>
> My understanding of this is that you can imagine include just pasting
> in the module code when its evaluated. So any changes to the module B
> after the include won't be included in the class D, because the
> copy&paste into the class has already happened.
>
> HTH,
> Chris

D'oh! I should have looked before I leaped. From Pickaxe:

"Second, a Ruby include does not simply copy the module's instance
methods into the class. Instead, it makes a reference from the class
to the included module. If multiple classes include that module,
they'll all point to the same thing. If you change the definition of a
method within a module, even while your program is running, all
classes that include that module will exhibit the new
behavior." (http://www.rubycentral.com/book/tut_modul...)

It looks like it's just nested includes after the fact that's the
issue.

Sorry,
Chris

Ken Bloom

7/2/2007 4:14:00 AM

0

On Mon, 02 Jul 2007 10:51:06 +0900, Vasco Andrade e Silva wrote:

> module A
> def a; :a; end
> end
>
> module B
> include A
> def b; :b; end
> end
>
> module C
> def c; :c; end
> end
>
> class D
> include B
> end
>
> D.new.a #=> :a ## Ok for me
> D.new.b #=> :b ## Ok for me
>
> module B
> include C
> end
>
> D.new.c #=> NoMethodError: undefined method `c' for #<D:0xb7cb985c>

D.included_modules #=> [B, A, Kernel]

If the behavior you expect to occur were occuring, there's no reason why
A would need to be listed in this list, since B would take care of
everything.

Apparently, method resolution doesn't recurse from B to A, rather `include
B' adds B and all of B's included modules directly into D's list of
included modules. Since C was added to B after this had happened, C
couldn't be added to D's list of included modules.

--Ken

--
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu...

Axel Etzold

7/2/2007 8:08:00 AM

0

Dear Vasco,

it seems like you wanted to include something before it is
defined.
The following worked for me:

module A
def a; :a; end
end

module B
include A
def b; :b; end
end

module C
def c; :c; end
end

module B # <------ interchanged these
include C
end

class D # <------ interchanged these
include B
end

D.new.a #=> :a ## Ok for me
D.new.b #=> :b ## Ok for me


p D.new.c #=>:c ## Ok for you?


Best regards,

Axel
--
Psssst! Schon vom neuen GMX MultiMessenger gehört?
Der kanns mit allen: http://www.gmx.net/de/go/mult...

Alex Gutteridge

7/2/2007 8:32:00 AM

0

On 2 Jul 2007, at 10:51, Vasco Andrade e Silva wrote:

> Hi,
>
> could someone check and comment if this is something that i don't
> understand well or a ruby "somehow" problem? please
>
> Here's the code:
>
> module A
> def a; :a; end
> end
>
> module B
> include A
> def b; :b; end
> end
>
> module C
> def c; :c; end
> end
>
> class D
> include B
> end
>
> D.new.a #=> :a ## Ok for me
> D.new.b #=> :b ## Ok for me
>
> module B
> include C
> end
>
> D.new.c #=> NoMethodError: undefined method `c' for #<D:
> 0xb7cb985c> ##
> This is not ok for me.
>
> Thanks,
> Vasco Andrade e Silva
>
> --
> Posted via http://www.ruby-....
>

I think you've found an interesting edge case for modules and mixins.
Redefining a module only seems to work to one 'level'. So this works:

irb(main):001:0> module FooBar
irb(main):002:1> end
=> nil
irb(main):003:0> class Baz
irb(main):004:1> include FooBar
irb(main):005:1> end
=> Baz
irb(main):006:0> a = Baz.new
=> #<Baz:0x330568>
irb(main):007:0> module FooBar
irb(main):008:1> def foo; :foo; end
irb(main):009:1> end
=> nil
irb(main):010:0> a.foo
=> :foo

But not here (analogous to your example I think):

irb(main):011:0> module Bar
irb(main):012:1> def bar; :bar; end
irb(main):013:1> end
=> nil
irb(main):014:0> module FooBar
irb(main):015:1> include Bar
irb(main):016:1> end
=> FooBar
irb(main):017:0> a.bar
NoMethodError: undefined method `bar' for #<Baz:0x330568>
from (irb):18

We need a guru to explain why...

Alex Gutteridge

Bioinformatics Center
Kyoto University



Robert Dober

7/2/2007 9:09:00 AM

0

<snip>
> irb(main):016:1> end
> => FooBar
> irb(main):017:0> a.bar
> NoMethodError: undefined method `bar' for #<Baz:0x330568>
> from (irb):18
>
> We need a guru to explain why...
That is definitely not me, but there was a very interesting thread by
Tom (aka Trans) very recently and Pit provided a nice metaprogramming
tool to address the issue which is called "double inclusion". [ Sorry
I am bad at finding references to threads :( ]

As a matter of fact there is an easy way to update the method lookup chain
just continue as follows in your irb session:

irb(main):019:0> class Baz
irb(main):020:1> include FooBar # Play it again Sam
irb(main):021:1> end
=> Baz
irb(main):022:0> a.bar
=> :bar

It has something to do with the proxies that are created for included
modules, maybe a Guru will explain this in detail.

Cheers
Robert

>
> Alex Gutteridge
>
> Bioinformatics Center
> Kyoto University
>
>
>
>


--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

Vasco Andrade e silva

7/2/2007 4:08:00 PM

0

Hi,

Axel Etzold wrote:
> it seems like you wanted to include something before it is
> defined.

No. I wanted to use mixins for more than 'one level', as Alex Gutteridge
explain it:
>I think you've found an interesting edge case for modules and mixins.
>Redefining a module only seems to work to one 'level'. So this works:
> ...

I didn't know that this "problem" was called "double inclusion" (thanks
Robert) or "Dynamic Module Include Problem". After a quick search for
"double inclusion" you get:
http://eigenclass.org/hiki/The+double+inclusi...
http://www.ruby-...to...

If some Guru come along and see this thread maybe he/she could give a
more indepth answer.

Meanwhile...
Thank you guys,
Vasco

--
Posted via http://www.ruby-....