Why is the method resolution order different from python,common lisp,...?

thomas weidner <[email protected]> Sat, 4 Jun 2016 01:17:41 -0700 (PDT)
Newsgroups gmane.comp.lang.scala
Message-ID <[email protected]>
Hello,

I am just learning Scala, but have experience in several other languages. 
Reading "Programming in Scala 3rd edition", I am a bit confused about trait 
inheritance. Though the author claims trait inheritance are not multiple 
inheritance, he may be right when he has C++ in his mind, but compared to 
languages like Common Lisp or Python trait inheritance in Scala is just 
multiple inheritance in these languages. 

Nevertheless, computing the method resolution order (or class precedence 
list) is done differently in Scala. In CL or Python classes are ordered 
using two principles: 

   1. every class after it's superclasses (super traits) 
   2. If two classes appear in the same superclass list, their order is 
   this list has to be preserved in the final class precedence list. 

If these two relations induce a partial order, a linearization of this 
order is used as class precedence list. Scala seems to pursue a different 
approach, In a recursive approach it concatenates the previously 
constructed linearizations of all super classes in order, and just does not 
add any class again, which are already present. While this approach 
preserves property 1 from above, property 2 may be violated, for example:
class Base
trait A extends Base 
trait B extends A 
class Test extends Base with B with A
This results in the order Test, B, A, Base. Note that B actually is after 
A, although A is written after B in the superclass list of Test. Let's 
compare this to the same example in Python (Note that in Python the first 
superclass is the most important not the last one as in Scala):
class Base:pass
class A(Base):pass
class B(A):pass
class Test(A,B):pass
Entering this in the Python interpreter yields an exception: Cannot create 
a consistent method resolution order (MRO) for bases A, B. This is expected 
since A has to come before B as A is a superclass of B, but B has to come 
before A as A is after B in the superclass list of Test. This cycle cannot 
be linearized. 

In my opinion the Python result is more natural and error safe as the 
superclass order always respects the way I specify it, if this is not 
possible an error occurs. In Scala, on the other hand, if a supertrait does 
something weird, my superclass order can get mixed and become unexpected. 
If I rely on the order some stacked behaviour, my code can become wrong and 
the error is *very *subtle and hard to track. (Imagine I add behaviour as a 
trait another trait already implements, even worse imagine this changes in 
some library version). 

Nevertheless, if my supeclasses can be linearized in the Python sense, the 
obtained order seems to match the order Scala obtains for the same 
hierarchy, but I am not quite sure about this, I would have to prove this 
on paper.

So my question is: Why is Scala more relaxed than Python or Common Lisp 
constructing the class precedence list? Is there a good reason or is it 
just the way someone implemented it once (maybe because he was unaware of 
the issue)? Will this algorithm change to the Python version in the future 
(2.12/13/...)? 

Thanks for reading my post,
Thomas

-- 
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
For more options, visit https://groups.google.com/d/optout.