- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Controlling mixin order
Wed, 2012-01-18, 14:45
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
Wed, 2012-01-18, 15:51
#2
Re: Controlling mixin order
(forgot selecting reply to all)
On Wed, Jan 18, 2012 at 2:52 PM, Sciss <contact@sciss.de> wrote:
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.
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 postWell, 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.
http://jim-mcbeath.blogspot.com/2009/08/scala-class-linearization.html
(or the referred to Scala Language Specification (SLS), Chapter 5)
helps?
Wed, 2012-01-18, 16:01
#3
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.
Wed, 2012-01-18, 16:21
#4
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:
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.
Wed, 2012-01-18, 16:41
#5
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.
>
>
Wed, 2012-01-18, 17:21
#6
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.
Wed, 2012-01-18, 17:41
#7
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.
Wed, 2012-01-18, 17:51
#8
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.
Wed, 2012-01-18, 18:21
#9
Re: Annotation @inline
On Wed, Jan 18, 2012 at 5:56 PM, Alexandr Litvinov <dvigal@yandex.ru> wrote:
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
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
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