I like to use an example to illustrate something here. Whilst playing with Scala, i find myself writing code like this
class MyTest {
def printSomething = println("blah blah blah")
def compute1Value = 41 * 41
def compute2Value = (41*41*2, 1)
}
object SimpleTest extends App {
def test1(a : {def printSomething: Unit ; def compute1Value: Int; def compute2Value: Tuple2[Int, Int]} ) {
.... // do something
}
I thought nothing special here. Compiled it and it works. But i thought i should be able to write something more generic than that because the structural subtyping technique here is REALLY useful in real world applications but there're caveats because of type erasure (this post isn't about that)
So i proceeded to modify the type of 'a' in 'test1' to become like this
...
def test1(a : {def print1Line: Unit; def fn1:Function0[Int]; def fntuple2: Function0[Tuple2[Int,Int]]}) {
.. // do something
}
But this didn't compile. Hmm...(honestly, WTF was the word that came to my mind) what happened. Afaik, it should work because i have a valid function definition on both LHS & RHS of the equation. However, after figuring out what happened by examining the java bytecode output i realized it and the following definition works
...
def test1(a : {def print1Line: Unit; def compute1Value:Int; def compute1Value2: Tuple2[Int,Int]} ) {
... // do something
}
Mystery solved. Don't get me wrong here but you should probably be able to find the answer by examining the Scala Language Specification & still i chose to de-assemble the code and from the output below you should be able to guess that the return type was determined and instead embedded into the signature of the function.
...
public int compute1Value();
Code:
0: sipush 1681
3: ireturn
public scala.Tuple2 compute1Value2();
Code:
0: new #24; //class scala/Tuple2$mcII$sp
3: dup
...
Alternatively, the following code works too
class MyAnonFnClass {
def print1Line = println("blah blah blah")
def fn1 = new Function0[Int] {
def apply() = 41 * 41}
def fntuple2 = new Function0[Tuple2[Int,Int]] {
def apply() = (41 * 41 * 2,1) }
}
object SimpleTest extends App {
def test1(a : {def print1Line: Unit; def fn1:Function0[Int]; def fntuple2: Function0[Tuple2[Int,Int]]}) {
... // do something
}
This definition of "test1" is what i like better but the definitions of "fn1" and "fntuple2" is somewhat awkward. Still, some say it doesn't look right ... there're better ways of writing this and an example is that of James Iry at stackoverflow
0 comments:
Post a Comment