Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why scala uses reflection to call method on structural type?

If function accepts structural type, it can be defined as:

def doTheThings(duck: { def walk; def quack }) { duck.quack }

or

type DuckType = { def walk; def quack  }
def doTheThings(duck: DuckType) { duck.quack }

Then, you can use that function in following way:

class Dog {
    def walk { println("Dog walk") }
    def quack { println("Dog quacks") }
}

def main(args: Array[String]) {
    doTheThings(new Dog);
}

If you decompile (to Java) the classes generated by scalac for my example, you can see that argument of doTheThings is of type Object and the implementation uses reflection to call methods on the argument (i.e.duck.quack)

My question is why reflection? Isn't it possible just to use anonymous and invokevirtual instead of reflection?

Here is way to translate(implement) the structural type calls for my example (Java syntax, but the point is the bytecode):

class DuckyDogTest {
  interface DuckType {
    void walk();
    void quack();
  }

  static void doTheThing(DuckType d) {
    d.quack();
  }

  static class Dog {
    public void walk() { System.out.println("Dog walk"); }
    public void quack() { System.out.println("Dog quack"); }
  }

  public static void main(String[] args) {
    final Dog d = new Dog();
    doTheThing(new DuckType() {
      public final void walk() { d.walk(); }
      public final void quack() { d.quack();}
    });
  }
}
like image 307
Op De Cirkel Avatar asked Dec 16 '11 19:12

Op De Cirkel


People also ask

What is Scala reflection?

Scala reflection enables a form of metaprogramming which makes it possible for programs to modify themselves at compile time. This compile-time reflection is realized in the form of macros, which provide the ability to execute methods that manipulate abstract syntax trees at compile-time.

Does Scala have duck typing?

Gettings Our Ducks in a Row Fortunately, Scala allows us to write idiomatic code to achieve the same results as duck typing.


1 Answers

Consider a simple proposition:

type T = { def quack(): Unit; def walk(): Unit }
def f(a: T, b: T) = 
  if (a eq b) println("They are the same duck!")
  else        println("Different ducks")

f(x, x) // x is a duck

It would print Different ducks under your proposal. You could further refine it, but you just cannot keep referential equality intact using a proxy.

A possible solution would be to use the type class pattern, but that would require passing another parameter (even if implicit). Still, it's faster. But that's mostly because of the lameness of Java's reflection speed. Hopefully, method handles will get around the speed problem. Unfortunately, Scala is not scheduled to give up on Java 5, 6 and 7 (which do not have method handles) for some time...

like image 192
Daniel C. Sobral Avatar answered Nov 15 '22 19:11

Daniel C. Sobral