15 May 22:24
Re: Method lookup for modules included in modules
From: Rick DeNatale <rick.denatale <at> gmail.com>
Subject: Re: Method lookup for modules included in modules
Newsgroups: gmane.comp.lang.ruby.general
Date: 2008-05-15 20:24:32 GMT
Subject: Re: Method lookup for modules included in modules
Newsgroups: gmane.comp.lang.ruby.general
Date: 2008-05-15 20:24:32 GMT
On Thu, May 15, 2008 at 10:59 AM, Mark Wilden <mark <at> mwilden.com> wrote: > On May 14, 2008, at 10:05 PM, ara.t.howard wrote: > >>> Here's my problem. If A1 doesn't contain the method, what causes the >>> search to backtrack to the B proxy and follow its super pointer to the C >>> proxy? This "backtracking" seems counter to the purported "linear" lookup >>> order. (This is just a conceptual problem for me - it's obvious what the >>> lookup order is, and it's easy to verify.) >> >> as each module in included in the target, it's entire lookup chain is >> added to that target - therefore no 'backtracking' is required, we just end >> up with a long line that, when followed, happens to give the appearance if >> backtracking. > > I do understand that that's how it works in practice. I was trying to > understand the process in terms of its implementation via proxies, klass, > super and m_tbl. If it were truly implemented as a single long chain, then > that would require (in my example) that the A2 proxy's super points to the B > proxy. Hmmm....I wonder if that's indeed the case, as you imply? module A1; end; module A2; end; module B; include A1; end module C; include A2; end class D; include C; include B; end results in the chains: A1 A1 B -> proxy1(A1) C-> proxy2(A2) D->proxy5(B)->proxy6(A1)->proxy3(C)->proxy4(A2)->Object->proxy0(Kernel) where proxyn indicates the nth module-proxy in creation order. When you include a module in a class, the current chain is searched to see if the module is already included and doesn't re-include it, and includes in a given class or module executed later are inserted before earlier includes in the same class or module, so the chain for the original set of modules and classes: module A; end; module B; include A; end module C; include A; end class D; include B; include C; end The chain for D looks like this: D->proxy(C)->proxy(B)->proxy(A)->Object->proxy(Kernel) This can lead to some small surprises for some people. Ruby doesn't include a proxy to a given module more than once in any inheritance chain, because of the way it implements finding overridden methods when resolving super. MRI doesn't keep track of the place in the chain where it found the currently executing method, so to find the method to be invoked for super, it searches again from the start until it finds the current METHOD, then searches from the next link in the chain. If a module proxy were repeated then this wouldn't work because some cases would loop. See the two articles below: http://talklikeaduck.denhaven2.com/articles/2007/06/02/chain-chain-chain http://talklikeaduck.denhaven2.com/articles/2007/11/03/a-chat-with-matz-classs-variable-reversion-and-a-mystery-explained -- -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/
RSS Feed