Scala 2.9.x’s Dynamic support allows you to “catch” a missing method call. This is a familiar concept in dynamic languages such as Groovy. In essence, I have an object that includes a special method that will be called when the caller invokes a method that does not appear in the object. Allow me to demonstrate:
class D extends Dynamic {
def ide() = {
"ide"
}
def applyDynamic(name: String)(args: Any*) = {
name match {
case "idea" => "rocks"
case "eclipse" => "boo"
case _ => "what?"
}
}
}
Now, when I have an instance of the class (val d = new D), I can call the method ide and receive "ide" as the result. This is not a great surprise. However, in addition to the ide method, the instance d allows me to call method with arbitrary name, with arbitrary arguments. Methods that are not “statically” matched bubble down to the applyDynamic method, whose code will decide what to do. So, in the example above, I can now call these methods:
val d = new D println(d.eclipse()) println(d.idea()) println(d.netBeans())
The output of this little gem of programming will be
boo rocks what?
Building
You must tell the Scala compiler to allow the usage of the Dynamic trait; to do so, all you have to do is to include the -Xexperimental command line parameter. I tried to do just that using the internal FSC support in IntelliJ IDEA’s Nika EAP. Unfortunately, it kept failing, even though I added the FSC parameter in the Scala compiler settings:

It turns out that the IntelliJ IDEA Scala plugin does not pass the FSC command line options to the internal FSC server. Luckily, the fix was quite simple.
Scala plugin update
I cloned the plugin’s repository git clone git://git.jetbrains.org/idea/scala-plugin.git and updated the org…compiler.ScalacBackendCompiler to include the FSC options. With the fix in place, I can now use IntelliJ IDEA’s FSC compiler’s -Xexperimental support, which includes support for the Dynamic trait usage. Unfortunately, the IDE still reports the missing methods as problems, though the code compiles & runs correctly.
Check out the bug and the diff of a fix at http://youtrack.jetbrains.net/issue/SCL-3805.
Why?
You might be asking why I would need that? Surely, the point in Scala is that it is strongly-typed language. Adding this dynamic tomfoolery feels wrong. It is important to remember that the dynamic support in Scala is [probably] intended to allow us to write domain-specific languages more easily and perhaps to support integration of the other dynamic languages on the Java platform.
It is tempting to use the Dynamic trait to implement equivalents of the findXXX pattern in Grails and Rails and to use it in the implementation of some builder objects. However, I don’t think the finder pattern is suitable to typesafe systems (the nature of the applyDynamic method is to potentially return Any). And the builders are best implemented using implicits that turn the starting values into instances of the builder, allowing you to then call the methods of the builder instances.


Just starting to learn Scala, have been exploring Groovy and Grails for about a year now.
Have grown tired of Grails, just an unpleasant experience overall, despite various excellent features (routing, filters, GORM, validation, views, REST, etc.). Class reloading works for the most part, but then you hit the dreaded, no hibernate session exists, or other restart-required glitch, which entails several trips down wtf-am-i-doing-lane as you wait 20+ seconds for a simple restart.
Saying that, Scala may have similar issues, although on barebones Scalatra + Scalate + JDBC stack I am hoping that is not the case!
Have been looking for a method missing option in Scala. Dynamic finders a la findByFoo do not seem inherently wrong, perhaps a necessary evil in regard to writing DSLs?
I understand that scala is strongly typed; however, in some cases, it may make sense to use Dynamic. For example,
val cust = Customer.findByEmail(‘foo@abc.com’)
val sub = Subscriber.findAllByActive(true)
would be very nice, imo.
How to implement, being new to Scala, is unclear at this point
It may not be so easy to pull off if Dynamic must return Any and cannot be overridden to return a custom type (e.g. Customer class that derives from Domain, where Domain would contain the findBy* logic)
For the data operations, you might want to take a look at Scalad, which allows you to write something like
val users = select(list[User]) // users is now List[User] obtained by running, in effect “select * from User”
val firstUser = select(head[User]) // the first User object
all the way down to the more complex
val m1 = head[User] >>= (u => head map (u2 => (u u2)))
val firstTwo = selector(m1)
val a2Something = firstTwo(“username” like “a2%”)
// a2Something is (Option[User], Option[User]) or None if there aren’t two or more matching results.
Many more details are at http://www.cakesolutions.org/scalad.html
scalad looks interesting, just not yet my cup of tea (I need to adjust to and learn the scala way of doing things).
For example, while:
val users = select(list[User])
is readable, I prefer:
val users = User.list()
as well as:
val order = findByOrderID(23)
The latter 2 cases would require Dynamic and/or have User extend from a Domain parent class that contains list() method along with findBy* method missing logic.
Again, I need to learn scala, there’s a method to the madness, clearly
, but 1/2 way through Odersky Programming in Scala is not enough, in the kindergarten stage at this point…
You’re right, User.list() looks right, but select(list[User]) gives you much more control. Specifically, list[User] is an interatee which returns the entire result. You can think of a paging iteratee, page, which would allow you to do something like select(page[User](20, 10)). This would give you a page of 10 records starting with record number 20. I will have to think about this one for a bit…
Implementing the list method in the User class would pollute your domain. Why should the domain class User be aware of the fact that it will be persisted? ActiveRecord does that, and for small apps, this is OK. However, for larger applications, I prefer to have the domain clean.
Keep an eye on the developments in Scalad; I am still trying to formulate approach that is both type-safe, that brings in the power of functional programming, and yet is easy to use.