This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Controlling mixin order

9 replies
Rüdiger Klaehn
Joined: 2009-06-02,
User offline. Last seen 42 years 45 weeks ago.

Hi all,

I have the following situation: a number of stackable traits
(A,B,C,...) that can be mixed in or not, but if they are mixed in I
want to make sure that they are mixed in in the correct order. A B or
A C or B C is ok, but not B A. You get the idea.

What is the easiest way to ensure this at compile time? If it is
tricky to do this at compile time, is there at least an easy way to
ensure proper order at runtime so that the creation of an object with
the wrong mixin order fails?

best regards,

Rüdiger

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Controlling mixin order

why, what would happen if the order is B A ? maybe you want to avoid some overrides ? you could try to make some methods `final`.

otherwise, maybe this post

http://jim-mcbeath.blogspot.com/2009/08/scala-class-linearization.html

(or the referred to Scala Language Specification (SLS), Chapter 5)

helps?

best, -sciss-

On 18 Jan 2012, at 13:44, rklaehn wrote:

> Hi all,
>
> I have the following situation: a number of stackable traits
> (A,B,C,...) that can be mixed in or not, but if they are mixed in I
> want to make sure that they are mixed in in the correct order. A B or
> A C or B C is ok, but not B A. You get the idea.
>
> What is the easiest way to ensure this at compile time? If it is
> tricky to do this at compile time, is there at least an easy way to
> ensure proper order at runtime so that the creation of an object with
> the wrong mixin order fails?
>
> best regards,
>
> Rüdiger

Rüdiger Klaehn
Joined: 2009-06-02,
User offline. Last seen 42 years 45 weeks ago.
Re: Controlling mixin order
(forgot selecting reply to all)

On Wed, Jan 18, 2012 at 2:52 PM, Sciss <contact@sciss.de> wrote:
why, what would happen if the order is B A ? maybe you want to avoid some overrides ? you could try to make some methods `final`.

The traits are not completely independent but "stack" on a method, so making things final is not an option. 
The data structure in question is a tree representing some kind of scene graph, where each node may or may not have children, may or may not have properties, etc. For each thing that may be present, I have a trait which implements the logic. For example I have a HasChildren trait that is responsible for calling a method (updated, paint, ...) on the children if the method updated is called on the node itself. I also have a HasProperties trait that does some things to the arguments and then calls the super method with the modified arguments. Now I always want the HasChildren trait to be mixed in first before the HasProperties trait so that the changes that are made in the HasProperties method are being properly forwarded to the children. This is just one of many examples.
You might argue that stackable traits or inheritance in general is evil anyway, but the whole thing works quite well if you add the traits in the right order, and in any case I can't think of a good alternative anyway.  
otherwise, maybe this post

http://jim-mcbeath.blogspot.com/2009/08/scala-class-linearization.html

(or the referred to Scala Language Specification (SLS), Chapter 5)

helps?

Well, that tells me in great detail how the linearization works, so it is useful. But it does not help a stupid user (or myself if I am tired and/or distracted) from mixing the traits in in the wrong order and producing a difficult to find bug. 
Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Controlling mixin order

maybe some protected 'constraints methods':

trait Stack {
protected def _require_a_before_b {}
}

trait A extends Stack {
override protected def _require_a_before_b {}
}

trait B extends Stack {
final override protected def _require_a_before_b {}
}

trait C extends Stack {
}

new A with B {} // ok
new A with C {} // ok
new B with C {} // ok
new B with A {} // forbidden

?

best, -sciss-

On 18 Jan 2012, at 14:42, Rüdiger Klaehn wrote:

> (forgot selecting reply to all)
>
> On Wed, Jan 18, 2012 at 2:52 PM, Sciss wrote:
> why, what would happen if the order is B A ? maybe you want to avoid some overrides ? you could try to make some methods `final`.
>
> The traits are not completely independent but "stack" on a method, so making things final is not an option.
>
> The data structure in question is a tree representing some kind of scene graph, where each node may or may not have children, may or may not have properties, etc. For each thing that may be present, I have a trait which implements the logic. For example I have a HasChildren trait that is responsible for calling a method (updated, paint, ...) on the children if the method updated is called on the node itself. I also have a HasProperties trait that does some things to the arguments and then calls the super method with the modified arguments. Now I always want the HasChildren trait to be mixed in first before the HasProperties trait so that the changes that are made in the HasProperties method are being properly forwarded to the children. This is just one of many examples.
>
> You might argue that stackable traits or inheritance in general is evil anyway, but the whole thing works quite well if you add the traits in the right order, and in any case I can't think of a good alternative anyway.
>
> otherwise, maybe this post
>
> http://jim-mcbeath.blogspot.com/2009/08/scala-class-linearization.html
>
> (or the referred to Scala Language Specification (SLS), Chapter 5)
>
> helps?
>
> Well, that tells me in great detail how the linearization works, so it is useful. But it does not help a stupid user (or myself if I am tired and/or distracted) from mixing the traits in in the wrong order and producing a difficult to find bug.

Rüdiger Klaehn
Joined: 2009-06-02,
User offline. Last seen 42 years 45 weeks ago.
Re: Controlling mixin order
That does work. But it requires a 'constraint method' for each pair where I want to define the order, and it also requires defining all these 'constraint methods' in the base object just in case. I was hoping for something a bit simpler.
If I don't insist on compile time validation but just want an exception when an object with the wrong mixin order is instantiated, would that be possible using reflection? Something like
trait A { assert(mixedInBefore(classOf[B]))}?

On Wed, Jan 18, 2012 at 3:48 PM, Sciss <contact@sciss.de> wrote:
maybe some protected 'constraints methods':

trait Stack {
  protected def _require_a_before_b {}
}

trait A extends Stack {
  override protected def _require_a_before_b {}
}

trait B extends Stack {
  final override protected def _require_a_before_b {}
}

trait C extends Stack {
}

new A with B {}   // ok
new A with C {}   // ok
new B with C {}   // ok
new B with A {}   // forbidden

?

best, -sciss-



On 18 Jan 2012, at 14:42, Rüdiger Klaehn wrote:

> (forgot selecting reply to all)
>
> On Wed, Jan 18, 2012 at 2:52 PM, Sciss <contact@sciss.de> wrote:
> why, what would happen if the order is B A ? maybe you want to avoid some overrides ? you could try to make some methods `final`.
>
> The traits are not completely independent but "stack" on a method, so making things final is not an option.
>
> The data structure in question is a tree representing some kind of scene graph, where each node may or may not have children, may or may not have properties, etc. For each thing that may be present, I have a trait which implements the logic. For example I have a HasChildren trait that is responsible for calling a method (updated, paint, ...) on the children if the method updated is called on the node itself. I also have a HasProperties trait that does some things to the arguments and then calls the super method with the modified arguments. Now I always want the HasChildren trait to be mixed in first before the HasProperties trait so that the changes that are made in the HasProperties method are being properly forwarded to the children. This is just one of many examples.
>
> You might argue that stackable traits or inheritance in general is evil anyway, but the whole thing works quite well if you add the traits in the right order, and in any case I can't think of a good alternative anyway.
>
> otherwise, maybe this post
>
> http://jim-mcbeath.blogspot.com/2009/08/scala-class-linearization.html
>
> (or the referred to Scala Language Specification (SLS), Chapter 5)
>
> helps?
>
> Well, that tells me in great detail how the linearization works, so it is useful. But it does not help a stupid user (or myself if I am tired and/or distracted) from mixing the traits in in the wrong order and producing a difficult to find bug.


Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Controlling mixin order

trait Stack {
protected type Par = List[ Class[ _ ]]

identify( Nil )

protected def identify( parents: Par ) : Par = parents
}

trait A extends Stack {
override def identify( p: Par ) = {
val p1 = super.identify( p )
require( !p1.contains( classOf[ B ]), "A must be mixed in before B" )
classOf[ A ] :: p1
}
}

trait B extends Stack {
override def identify( p: Par ) : Par = classOf[ B ] :: super.identify( p )
}

new A with B {} // ok
new B with A {} // forbidden

this would require though that every crucial constraint trait provides an override for identity...

best, -sciss-

On 18 Jan 2012, at 15:05, Rüdiger Klaehn wrote:

> That does work. But it requires a 'constraint method' for each pair where I want to define the order, and it also requires defining all these 'constraint methods' in the base object just in case. I was hoping for something a bit simpler.
>
> If I don't insist on compile time validation but just want an exception when an object with the wrong mixin order is instantiated, would that be possible using reflection? Something like
>
> trait A {
> assert(mixedInBefore(classOf[B]))
> }?
>
> On Wed, Jan 18, 2012 at 3:48 PM, Sciss wrote:
> maybe some protected 'constraints methods':
>
> trait Stack {
> protected def _require_a_before_b {}
> }
>
> trait A extends Stack {
> override protected def _require_a_before_b {}
> }
>
> trait B extends Stack {
> final override protected def _require_a_before_b {}
> }
>
> trait C extends Stack {
> }
>
> new A with B {} // ok
> new A with C {} // ok
> new B with C {} // ok
> new B with A {} // forbidden
>
> ?
>
> best, -sciss-
>
>
>
> On 18 Jan 2012, at 14:42, Rüdiger Klaehn wrote:
>
> > (forgot selecting reply to all)
> >
> > On Wed, Jan 18, 2012 at 2:52 PM, Sciss wrote:
> > why, what would happen if the order is B A ? maybe you want to avoid some overrides ? you could try to make some methods `final`.
> >
> > The traits are not completely independent but "stack" on a method, so making things final is not an option.
> >
> > The data structure in question is a tree representing some kind of scene graph, where each node may or may not have children, may or may not have properties, etc. For each thing that may be present, I have a trait which implements the logic. For example I have a HasChildren trait that is responsible for calling a method (updated, paint, ...) on the children if the method updated is called on the node itself. I also have a HasProperties trait that does some things to the arguments and then calls the super method with the modified arguments. Now I always want the HasChildren trait to be mixed in first before the HasProperties trait so that the changes that are made in the HasProperties method are being properly forwarded to the children. This is just one of many examples.
> >
> > You might argue that stackable traits or inheritance in general is evil anyway, but the whole thing works quite well if you add the traits in the right order, and in any case I can't think of a good alternative anyway.
> >
> > otherwise, maybe this post
> >
> > http://jim-mcbeath.blogspot.com/2009/08/scala-class-linearization.html
> >
> > (or the referred to Scala Language Specification (SLS), Chapter 5)
> >
> > helps?
> >
> > Well, that tells me in great detail how the linearization works, so it is useful. But it does not help a stupid user (or myself if I am tired and/or distracted) from mixing the traits in in the wrong order and producing a difficult to find bug.
>
>

Alexander Litvinov
Joined: 2010-10-17,
User offline. Last seen 15 weeks 1 day ago.
Annotation @inline

Hi all,
I have a question about annotation "inline".
When should apply that annotation and how it work inside jvm?
For example, I have the function "pathCopy", this is function - tail
recursive and it will be called very often.
Thanks.

--
best regards,
Alexander.

H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
Re: Annotation @inline

@inline is a hint for the scala compiler, not for the vm.

-------- Original-Nachricht --------
> Datum: Wed, 18 Jan 2012 21:56:19 +0500
> Von: "Alexandr Litvinov"
> An: scala-user@googlegroups.com
> Betreff: [scala-user] Annotation @inline

> Hi all,
> I have a question about annotation "inline".
> When should apply that annotation and how it work inside jvm?
> For example, I have the function "pathCopy", this is function - tail
> recursive and it will be called very often.
> Thanks.
>
>
> --
> best regards,
> Alexander.

edmondo1984
Joined: 2011-09-14,
User offline. Last seen 28 weeks 3 days ago.
R: Re: Annotation @inline

In doubt put it everywhere!!
Inviato da BlackBerry(R) Wireless Handheld

-----Original Message-----
From: "Dennis Haupt"
Sender: scala-user@googlegroups.com
Date: Wed, 18 Jan 2012 17:22:40
To: Alexandr Litvinov;
Subject: Re: [scala-user] Annotation @inline

@inline is a hint for the scala compiler, not for the vm.

-------- Original-Nachricht --------
> Datum: Wed, 18 Jan 2012 21:56:19 +0500
> Von: "Alexandr Litvinov"
> An: scala-user@googlegroups.com
> Betreff: [scala-user] Annotation @inline

> Hi all,
> I have a question about annotation "inline".
> When should apply that annotation and how it work inside jvm?
> For example, I have the function "pathCopy", this is function - tail
> recursive and it will be called very often.
> Thanks.
>
>
> --
> best regards,
> Alexander.

Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: Annotation @inline
On Wed, Jan 18, 2012 at 5:56 PM, Alexandr Litvinov <dvigal@yandex.ru> wrote:
Hi all,
I have a question about annotation "inline".
When should apply that annotation and how it work inside jvm?
For example, I have the function "pathCopy", this is function - tail recursive and it will be called very often.
Thanks.

If the method is suitably small and called often enough, the HotSpot Compiler will probably inline it. Use of @inline, to ask the Scala compiler to perform the same optimization statically, has an advantage when it enables other optimizations that aren't possible at runtime, such as closure or boxing elimination.
Take a look at these slides for an overview: http://www.wiki.jvmlangsummit.com/ScalaOptimization, or check out Iulian's thesis for a really detailed look: http://www.iulidragos.org/?page_id=62
-jason

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland