Practical uses of a Dynamic type in Scala

前端 未结 3 468
耶瑟儿~
耶瑟儿~ 2020-12-07 22:41

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?

相关标签:
3条回答
  • 2020-12-07 23:06

    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..

    0 讨论(0)
  • 2020-12-07 23:13

    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

    0 讨论(0)
  • 2020-12-07 23:25

    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")
    
    0 讨论(0)
提交回复
热议问题