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

Reply via email to