# Included in Kernel, yet won't show up in \`C::ancestors'?

**URL:** <https://www.ruby-forum.com/t/included-in-kernel-yet-wont-show-up-in-c-ancestors/135206>\
**Category:** Ruby\
**Created:** [April 19, 2008, 7:21am UTC](https://www.ruby-forum.com/t/included-in-kernel-yet-wont-show-up-in-c-ancestors/135206 "2008-04-19T07:21:48Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![unnali](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/97f17d/32.png) [@unnali](https://www.ruby-forum.com/u/unnali)\
**Post date:** [April 19, 2008, 7:21am UTC](https://www.ruby-forum.com/t/included-in-kernel-yet-wont-show-up-in-c-ancestors/135206/1 "2008-04-19T07:21:48Z")

</div>

Hi all,

I’m fairly sure I’m a long way down the path of madness with this one.  
Please bare with me. I’ve been on this for some time now.

I’ve been trying to work out the order in which items appear in  
“SomeClass::ancestors”. I thought I had it before:

[SomeClass, SomeClass’sIncludedModules…, SuperClass,  
SuperClass’sIncludedModules, SuperSuperClass, …]

I constructed a test case:

$ ruby -e ‘module M; end; module N; end; class A; include M; end; class  
B \<  
A; include N; end; p B.ancestors’  
[B, N, A, M, Object, Kernel]

This is the expected result! But then I wondered… what if we included  
something in `M’? It shouldn’t appear according to my theory here, since  
M  
is not included by SomeClass itself. But, sure enough, it does appear.  
(which makes sense!)

The reason I presumed this is because if I include a module in Kernel,  
it  
won’t appear in the list of any Class’s ancestors, yet it will appear in  
Kernel’s:

$ ruby -e ‘module A; end; module Kernel; include A; end; class C; end; p  
C.ancestors; p Kernel.ancestors’  
[C, Object, Kernel]  
[Kernel, A]

This confused me slightly, since it goes directly against what we  
experience  
with this:

$ ruby -e ‘module A; end; module B; include A; end; class C; include B;  
end;  
class D \< C; end; p D.ancestors’  
[D, C, B, A, Object, Kernel]

… that is, the modules included by a superclass’s included module  
appearing  
in the ancestors list. In the previous example, Object (superclass of C)  
includes Kernel, and we don’t see Kernel’s included A. Here, C  
(superclass  
of D) includes B, yet we also see A. So, that proves that theory wrong.

In frustation, and in trying to work this out, my test case became  
larger  
and larger… I think this provides about all the useful data we could  
hope  
for:

$ ruby -e ‘module M; end; module N; end; module O; end; module P; end;  
module Q; end; module R; include Q; end; module M; include O; end;  
module  
Kernel; include P; end; class Object; include R; end; class A; include  
M;  
end; class B \< A; include N; end; p B::ancestors’  
[B, N, A, M, O, Object, R, Q, Kernel]

modules M, N, O, P, Q, R.  
M includes O  
Object includes R, R includes Q  
Kernel includes P

class A includes M  
class B derives from A, includes N

To start, [B, N, A …] shows that the included items are first, followed  
by  
the superclass.  
[… A, M, O, Object …] continues to demonstrate this, and also tells us  
that included items also have _their_ included items. [M’s O] Object is  
A’s  
superclass…  
[… Object, R, Q, Kernel …] agrees with the above results, showing that  
Object’s included R is there, and R’s included Q, and the Object’s  
included  
Kernel …  
[… Kernel] then ruins things little, since Kernel’s included P never  
makes  
it.

I have a feeling Kernel’s already being included by something (or it  
deriving from something-or-other) – I have no idea, really – has  
something  
to do with this. What interests me also is that Kernel::ancestors in  
this  
test _does_ return [Kernel, P].

This ended up being quite long and drawn out, and I hope this interested  
you, or that you may have some advice.

Cheers,  
Arlen.

---

<div class="post-metadata">

**Author:** ![unnali](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/97f17d/32.png) [@unnali](https://www.ruby-forum.com/u/unnali)\
**Post date:** [April 19, 2008, 9:10am UTC](https://www.ruby-forum.com/t/included-in-kernel-yet-wont-show-up-in-c-ancestors/135206/2 "2008-04-19T09:10:37Z")

</div>

Arlen C. wrote:

> I’m fairly sure I’m a long way down the path of madness with this one.  
> Please bare with me.

You may be stark, raving mad, but there’s nothing to be gained by group  
streaking.

SCNR. Maybe a few lols will help you solve the problem (or not), but  
that’s all I can offer at this hour.

---

<div class="post-metadata">

**Author:** ![unnali](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/97f17d/32.png) [@unnali](https://www.ruby-forum.com/u/unnali)\
**Post date:** [April 19, 2008, 11:40am UTC](https://www.ruby-forum.com/t/included-in-kernel-yet-wont-show-up-in-c-ancestors/135206/3 "2008-04-19T11:40:35Z")

</div>

On 19.04.2008 07:20, Arlen C. wrote:

> This ended up being quite long and drawn out, and I hope this interested  
> you, or that you may have some advice.

Relax. Don’t worry to much. Take a nap.

Kernel is special so you cannot expect ordinary mechanisms to apply. If  
there was not end to inclusion / inheritance chain there would be  
endless recursion (e.g. during method lookup). So the chain has to be  
broken at _some_ point.

Cheers

robert

---

<div class="post-metadata">

**Author:** ![unnali](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/97f17d/32.png) [@unnali](https://www.ruby-forum.com/u/unnali)\
**Post date:** [April 19, 2008, 1:53pm UTC](https://www.ruby-forum.com/t/included-in-kernel-yet-wont-show-up-in-c-ancestors/135206/4 "2008-04-19T13:53:16Z")

</div>

On Sat, Apr 19, 2008 at 7:20 AM, Arlen C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> with this:
> 
> $ ruby -e ‘module A; end; module B; include A; end; class C; include B; end;  
> class D \< C; end; p D.ancestors’  
> [D, C, B, A, Object, Kernel]
> 
> … that is, the modules included by a superclass’s included module appearing  
> in the ancestors list. In the previous example, Object (superclass of C)  
> includes Kernel, and we don’t see Kernel’s included A. Here, C (superclass  
> of D) includes B, yet we also see A. So, that proves that theory wrong.

You’ve bumped here into what some people call the double inclusion  
problem or the dynamic inclusion problem. With modules in modules, the  
order of the inclusions matters. A slightly reordered version of your  
last example is this:

$ ruby -e ‘module A; end; module B; end; class C; include B; end;  
module B ; include A ; end ; class D \< C; end; p D.ancestors ; p  
B.ancestors’  
[D, C, B, Object, Kernel]  
[B, A]

See how A disappeared from the ancestors even though it is still  
included in A? This is what you experience with Kernel: Kernel was  
included in Object before you included your own module in it. This is  
because of the way module inclusion is implemented in Ruby. In  
database terms, Ruby’s internal representation is denormalized for  
efficiency reasons. The danger is inconsistency, which is what happens  
here.

Note that you can force inclusion of recursively included modules by  
reincluding the top-level module after recursive inclusions, like  
this:

ruby -e ‘module A; end; module Kernel; include A; end; class Object ;  
include Kernel ; end ; class C; end; p C.ancestors’  
[C, Object, Kernel, A]

The reinclusion of Kernel in Object doesn’t result in it being  
included twice (Ruby tries to prevent that from happening), but it  
does update the recursive inclusion.

So basically, Kernel is nothing special in this regard, except that by  
its predefinition it resulted in a different inclusion order than your  
other test cases.

HTH,

Peter

---

<div class="post-metadata">

**Author:** ![unnali](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/97f17d/32.png) [@unnali](https://www.ruby-forum.com/u/unnali)\
**Post date:** [April 19, 2008, 2:10pm UTC](https://www.ruby-forum.com/t/included-in-kernel-yet-wont-show-up-in-c-ancestors/135206/5 "2008-04-19T14:10:53Z")

</div>

Hi Peter,

On Sat, Apr 19, 2008 at 9:52 PM, Calamitas [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> You’ve bumped here into what some people call the double inclusion  
> problem or the dynamic inclusion problem. With modules in modules, the  
> order of the inclusions matters.

> The reinclusion of Kernel in Object doesn’t result in it being  
> included twice (Ruby tries to prevent that from happening), but it  
> does update the recursive inclusion.

> So basically, Kernel is nothing special in this regard, except that by  
> its predefinition it resulted in a different inclusion order than your  
> other test cases.

Amazing!

Thank you very much! You answered my (rather unnecessarily difficultly  
worded) question perfectly! It is somewhat comforting to know this is an  
implementation detail.

HTH,

> Peter

Warmest thanks and regards,  
Arlen
