--000e0cd2982495752604654ef988
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

> This is very surprising, I always thought the ancestor tree was inspected
>> at
>> method call time,
>>
>
> That's true, but the point made was that it is _built_ on inclusion time.


Sorry, I should have been more clear. By using the word 'tree' I was
implying that the whole ancestor tree is walked at method call time. What
actually happens is that it is walked and flattened to an array at include
time, and this flat array is used to look up methods at call time. At least,
this is what it looks like -- I've no idea what the underlying VM is doing.


>
>  IMO this could be done better and preserve a bit more dynamism.
>>
>
>  Would be interested to hear other people's thoughts on this. It's kind of
>> an
>> edge case, but my opinion is that this behaviour is contrary to much of
>> Ruby's dynamism, and is inconsistent: if you add methods to M, they become
>> available to C, so why not new ancestors? Also, it means the ancestry tree
>> looks different depending on who you ask. Having said that, experience
>> tells
>> me that "fixing" it would introduce a serious performance overhead for the
>> whole language.
>>
>
> More than that: existing code may be broken.  There are good reasons not to
> "fix" this, because otherwise a change of a module has a side effect on a
> totally different class.  I cannot remember having seen this discussed in
> the last years (which does not necessarily mean something) but I doubt that
> many people see this as limitation.
>
> Given that, the infrequency of this issue surfacing and the unknown risk of
> change I vote for "no change".


For sure, the Ruby ecosystem is too big to know how changing this might
affect existing code. I'm really asking because I want to know which option
people consider more elegant, and also because I maintain my own
Ruby-in-JavaScript object system which has nothing like Ruby's user base, so
I'm more free to tinker with it.

By the way, I just noticed this:

>> module M; end
nil
>> class A; end
nil
>> class B < A; end
nil
>> B.ancestors
[B, A, Object, Kernel]
>> A.send :include, M
A
>> B.ancestors
[B, A, M, Object, Kernel]

That is, adding a module to an ancestor class affects the descendants. This
could be seen as an inconsistency in Ruby's design, depending on how you
think about classes and modules and how they are implemented. In my
implementation everything inheritance-related is handled using modules so I
would need to add a bunch of special cases to handle some of the asymmetries
pointed out here.

--
James Coglan
http://github.com/jcoglan

--000e0cd2982495752604654ef988--