Practical uses of a Dynamic type in Scala
Besides integration with dynamic languages on the JVM, what are the other powerful uses of a Dynamic type in a statically typed language like Scala?
I guess a dynamic type could be used to implement several of the features found in JRuby, Groovy or other dynamic JVM languages, like dynamic metaprogramming and method_missing.
For example creating a dynamic query similar to Active Record in Rails, where a method name with parameters is translated to an SQL query in the background. This is using the method_missing functionality in Ruby. Something like this (in theory - have not tried to implement anything like this):
class Person(val id: Int) extends Dynamic {
def _select_(name: String) = {
val sql = "select " + name + " from Person where id = " id;
// run sql and return result
}
def _invoke_(name: String)(args: Any*) = {
val Pattern = "(findBy[a-zA-Z])".r
val sql = name match {
case Pattern(col) => "select * from Person where " + col + "='" args(0) + "'"
case ...
}
// run sql and return result
}
}
Allowing usage like this, where you can call methods 'name' and 'findByName' without having them explicitly defined in the Person class:
val person = new Person(1)
// select name from Person where id = 1
val name = person.name
// select * from Person where name = 'Bob'
val person2 = person.findByName("Bob")
If dynamic metaprogramming was to be added, the Dynamic type would be needed to allow invoking methods that have been added during runtime..
Odersky says the primary motivation was integration with dynamic languages: http://groups.google.com/group/scala-language/msg/884e7f9a5351c549
[edit] Martin further confirms this here
You might also use it for syntactic sugar on maps:
class DynamicMap[K, V] extends Dynamic {
val self = scala.collection.mutable.Map[K, V]()
def _select_(key: String) = self.apply(key)
def _invoke_(key: String)(value: Any*) =
if (value.nonEmpty) self.update(key, value(0).asInstanceOf[V])
else throw new IllegalArgumentException
}
val map = new DynamicMap[String, String]()
map.foo("bar") // adds key "foo" with value "bar"
map.foo // returns "bar"
To be honest this only saves you a couple of keystrokes from:
val map = new Map[String, String]()
map("foo") = "bar"
map("foo")
精彩评论