On 7/7/11 06:10 , Raoul Duke wrote:
now that you have experimented with scala + qi4j, what do you see as
the main benefits/differences of qi4j vs. scala's features like
mixins/traits? thanks for any brief summary keywords i can follow up
on myself.
Scalas traits are in bytecode translated into interface+static class
methods.
I.e. this:
trait HelloWorldMixin
{
def doStuff(): String =
{
"Do stuff"
}
}
gets translated (roughly) into this:
interface HelloWorldMixin
{
String doStuff();
public class $class
{
public static String doStuff(HelloWorldMixin object)
{
return "Do stuff";
}
}
}
---
So, for the vast bulk of mixin coding, where there's only one
implementation (like 99%), the trait syntax is superior. With just one
snag. There's no state in traits. Like, at all. Because it's all just
static methods. So the only way to get state into it is to either have a
class that the trait "decorates", or add methods that return the state,
a la Property methods. Same goes for any injected service you want
access to. Problem is, I have found it to be very useful to not have
just one class to model the data of an entity (this stuff is mostly for
entity modeling btw), and so "classes" don't work, i.e. you have to use
traits for everything, and then the "no state" rule becomes kind of a
bummer.
As for concerns, you can sort of do typed concerns in Scala, afaik, but
doing generic concerns (which is more useful, generally), is not
directly supported. But implementing concerns in Scala, and then use
Qi4j to bind it all together, kicks serious butt. Example:
class HelloThereConcern
extends ConcernOf[HelloWorldMixin2] with HelloWorldMixin2
{
override def sayHello(name: String) = next.sayHello("there "+name);
}
---
Very compact syntax. Here's a generic concern example:
@AppliesTo(Array(classOf[StringFilter]))
class ExclamationGenericConcern
extends GenericConcern
{
def invoke(composite: AnyRef, method: Method, args: Array[AnyRef]) =
next.invoke(composite, method, args)+"!"
}
class StringFilter
extends AppliesToFilter
{
def appliesTo(method: Method, mixin: Class[_], compositeType:
Class[_], fragmentClass: Class[_]) =
method.getReturnType.equals(classOf[String])
}
---
So, to summarize it seems to me that using Scala with Qi4j is an awesome
combo, if you can stand the fact that you have to use methods for all
state (persistent, injected stuff, temporary variables, etc.).
I still only have a couple of hours of Scala experience, i.e. what I
needed to make the bridge from Qi4j to Scala and back, but another thing
with Scala is that there seems to be quite a lot of variation in how you
can do the same thing. Let's look at Bruce Eckel's example from his
recent article(http://www.artima.com/weblogs/viewpost.jsp?thread=328540):
v.foreach((n:Double) => println(n))
=
v.foreach((n) => println(n))
=
v.foreach(n => println(n))
=
v.foreach(println(_))
=
v.foreach(println)
=
v foreach println
Now, is that super-duper-awesome, or just terribly confusing? I don't
know. Just seems like lotsa rules to understand while reading the code,
and each developer is going to do the same thing in six different ways.
Not structurally, just syntactically. If you read the article, the last
variation had to be pointed out by a commenter. So even Bruce Almighty
probably would've been confused by the last piece of code.
And then I go:
*shrug*
/Rickard
_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev