views:

107

answers:

2

Using a case construct for type-safe casting is easily done in scala. The following code ensures that square gets only called on objects which have an according type.

class O
class A extends O {
    def square(i: Int):Int = { i*i }
}
class B extends O {
    def square(d: Double):Double = { d*d }
}
class C extends O {}

def square(o: O) = o match {
    case a:A => print(a.square(3))
    case b:B => print(b.square(3.0))
    case c:C => print(9)
    case _ => print("9")
}

On the other hand, there are cases where it is not as easy to use the type information for casting and just checking for availability of a {def square(Int): Int} would be sufficient. Is there a construct in scala that allows for doing something similar to

def square(o: O) = o match {
    case a:{def square(Int):Int} => print(a.square(3))
    case b:{def square(Double):Double} => print(b.square(3.0))
    case _ => print("9")
}

Using implicit evidence parameters, it is possible to define methods depending on the availability of other methods. Is it also possible to call them only when they are defined?

+4  A: 

Structural typing expresses non-inheritance-constrained availability of members, so if you want a method to accept only values that bear a particular method, say def square(i: Int): Int, you use this notation:

class Squaring {
  type Squarable = { def square(i: Int): Int }
  def squareMe(s: Squarable): Int = s.square(17)
}

class CanSquare { def square(i: Int) = i * i }

val cs1 = new CanSquare
val s1 = new Squaring

printf("s1.squareMe(cs1)=%d%n", s1.squareMe(cs1))


s1.squareMe(cs1)=289

You should know that structural typing is implemented via reflection, but as of Scala 2.8, the reflection information is cached at the invocation site on a class-by-class basis (actual classes of supplied values).

Randall Schulz
The fact that it's implemented via reflection means that there's a performance penalty (calling methods via reflection is slower than regular method calls).
Jesper
I thought that was implied and it's why I mentioned it.
Randall Schulz
+1  A: 

It seems that type-classes appear to be the standard of applying an operation to many differing types. It's not looking up methods at runtime (well, it can, but not the pure pattern), but it could provide what you want.

trait Numeric[T] {
  def times(x :T, y : T) : T
}

object Numeric {
  implicit val doubleNumeric = new Numeric[Double] {
    def times(x : Double, y : Double) = x*y
  }
  implicit val intNumeric = new Numeric[Int] {
    def times(x : Int, y : Int) = x*y
  }
}

def square[A : Numeric](x : A) = implicitly[Numeric[A]].times(x,x)

If you're doing this in the scala REPL, make sure the object Numeric is a true companion object to trait Numeric. You can do this by wrapping the declaration in another object, say tmp, and then importing tmp._.

Next, just call square with different values:

scala> square(2)       
res6: Int = 4

scala> square(4.0)
res7: Double = 16.0

Scala actually provides a Numeric type class for use in numerical calculations, see: http://www.scala-lang.org/api/current/scala/math/Numeric.html

I also wrote an article on the type class pattern in Scala and methods of using it to adapt multiple APIs or do multiple dispatch here: http://suereth.blogspot.com/2010/07/monkey-patching-duck-typing-and-type.html

If you google for "scala type class" you should see a lot of information.

Part #2 - An actual respond_to?

If you really really wanted a respond_to in scala, you are somewhat SOL. This is because respond_to really is a dynamic concept. You are defining a method on a class that will be called if you attempt to call a method on the class that doesn't exist. Scala doesn't abstract over method calls the way some dynamic JVM languages do. This means there are no hooks into method calls for you to intercept and interact with. The best you could do is a form of interface adaptation, or some kind of aspect-oriented post-compilation hook to rewrite bytecode for you.

There is one magic piece we can utilize, and it too is used in some AOP frameworks: The Dynamic proxy.

scala> object AllPowerfulProxy extends InvocationHandler {                      
     | def invoke(proxy : AnyRef, m : Method, args : Array[AnyRef]) : AnyRef = {
     | println(" You really want to call " + m.getName + "?")
     | null // Maliciously Evil!
     | }
     | }
defined module AllPowerfulProxy

scala> def spawn[A : Manifest] : A = {
     |   val mf = implicitly[Manifest[A]]        
     |   java.lang.reflect.Proxy.newProxyInstance(mf.erasure.getClassLoader,
     |                                            Array(mf.erasure),
     |                                            AllPowerfulProxy).asInstanceOf[A]
     | }
spawn: [A](implicit evidence$1: Manifest[A])A

Now we can use it to spawn objects to any interface. Let's see what we can do:

scala> val x = spawn[TestInterface]
 You really want to call toString?
java.lang.NullPointerException
    at scala.runtime.ScalaRunTime$.stringOf(ScalaRunTime.scala:259)

You see what we did there? When the REPL tries to call toString on the result of an expression, it call it on our dynamic proxy. Since the proxy is a placeholder, the actual call is delegated to our AllPowerfulProxy class, how prints the message: "You really want to call toString?". The REPL then hits the null return and throws an exception. You see, using dynamic proxies moves errors to runtime, so you need to be very careful about instantiating objects and returning the correct types. Depending on the complexity of your system you should also worry about classLoaders. If you ever get a ClassCastException of Foo to Foo, then you know you're in class loader hell.

In any case, if you have other questions on dynamic proxies feel free to ask. In a statically typed languages, you're probably better off utilising type-classes and migrating to design patterns using them instead of the ones using respond_to. (You'll be surprised what you can accomplish with type classes and the type system).

jsuereth