Structural Type Dispatch in Scala
scala
Solution
`--` 1. In your example, I wouldn't use the `summary(o)` version, as this is not a very object oriented style of programming. When calling `o.summary` (you could drop the brackets as it has no side-effects), you are asking for the `summary` property of `o`. When calling `summary(o)`, you are passing `o` to a method that calculates the summary of `o`. I believe that the first approach is nicer :).
I haven't used structural type dispatch much, but I assume that it is best suited (in a large system) for the case where you would have to write an interface just because one method wants a type that has some method defined. Sometimes creating that interface and forcing the clients to implement it can be awkward. Sometimes you want to use a client defined in another API which conforms to your interface but doesn't explicitly implement it. So, in my opinion, structural type dispatch serves as a nice way to make the adapter pattern implicitly (saves on boilerplate, yay!).
`--` 2. Apparently if you call `summary(o)` and `o` is of `ObjectType`, `summary(o: ObjectType)` gets called (which does make sense). If you call `summary(bar)`, in which `bar` is not of `ObjectType`, two things can happen. The call compiles if `bar` has the method `summary()` of the right signature and name or otherwise, the call doesn't compile.
Example:
scala> case class ObjectType(summary: Double)
defined class ObjectType
scala> val o = ObjectType(1.2)
o: ObjectType = ObjectType(1.2)
scala> object Test {
| def summary(o: ObjectType) { println("1") }
| def summary(o: { def summary: Double}) { println("2")}
| }
defined module Test
scala> Test.summary(o)
1
Unfortunately, something like the following does not compile due to type erasure:
scala> object Test{
| def foo(a: {def a: Int}) { println("A") }
| def foo(b: {def b: Int}) { println("B") }
| }
:6: error: double definition:
method foo:(AnyRef{def b(): Int})Unit and
method foo:(AnyRef{def a(): Int})Unit at line 5
have same type after erasure: (java.lang.Object)Unit
def foo(b: {def b: Int}) { println("B") }
`--` 3. In a sense, structural type dispatch is more dynamic than generic methods, and also serves a different purpose. In a generic method you can say either: a. I want something of any type; b. I want something of a type that is a subtype of A; c. I'll take something that is a supertype of B; d. I'll take something that has an implicit conversion to type C. All of these are much stricter than just "I want a type that has the method `foo` with the right signature". Also, structural type dispatch does use reflection, as they are implemented by type erasure.
I don't know much about multimethods, but looking at the wikipedia article, it seems that multimethods in Scala can be achieved using pattern matching. Example:
def collide(a: Collider, b: Collider) = (a, b) match {
case (asteroid: Asteroid, spaceship: Spaceship) => // ...
case (asteroid1: Asteroid, asteroid2: Asteroid) => // ...
...
Again, you could use structural type dispatch - `def collide(a: {def processCollision()})`, but that depends on a design decision (and I would create an interface in this example).
`-- Flaviu Cipcigan`
Problem
I'm trying to get a better grasp of structural type dispatch. For instance, assume I have an iterable object with a `summary` method that computes the mean. So `o.summary()` gives the mean value of the list. I might like to use structural type dispatch to enable `summary(o)`. - Is there a set of best practices regarding `o.summary()` vs. `summary(o)`? - How does scala resolve `summary(o)` if I have a method `summary(o: ObjectType)` and `summary(o: { def summary: Double})` - How does structural type dispatch differ from multimethods or generic functions? Michael Galpin gives the following discription about structural type dispatch: Structural types are Scala’s version of “responds-to” style programming as seen in many dynamic languages. So like ``` def sayName ( x : { def name:String }){ println(x.name) } ``` Then any object with a method called name that takes no parameters and returns a string, can be passed to sayName: ``` case class Person(name:String) val dean = Person("Dean") sayName(dean) // Dean ```