Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Scala compiler for .NET ignore the meaning of val?

I am playing around with Scala. And I found 3 interesting things(the title is the third one ).

1 a local variable declared as val is not interpreted as final.

class HowAreVarAndValImplementedInScala {
  var v1 = 123
  val v2 = 456

  def method1() = {
    var v3 = 123
    val v4 = 456
    println(v3 + v4)
  }
}

if i compile the above scala code into bytecode and then decompile that into java, it looks like this:

public class HowAreVarAndValImplementedInScala
{
  private int v1 = 123;
  private final int v2 = 456;

  public int v1()
  {
    return this.v1;
  }

  public void v1_$eq(int x$1) { this.v1 = x$1; }

  public int v2() { return this.v2; }

  public void method1() {
    int v3 = 123;
    int v4 = 456;
    Predef..MODULE$.println(BoxesRunTime.boxToInteger(v3 + v4));
  }
}

we can see v2 is final, but v4 is not, why?

2 scala compiler for .net adds override keyword to a lot of(if not all) public instance methods

if we compile the scala code shown above into CIL and then decompile it into C#, it's like this:

public class HowAreVarAndValImplementedInScala : ScalaObject
{
  private int v1;
  private int v2;

  public override int v1()
  {
    return this.v1;
  }

  public override void v1_$eq(int x$1)
  {
    this.v1 = x$1;
  }

  public override int v2()
  {
    return this.v2;
  }

  public override void method1()
  {
    int v3 = 123;
    int v4 = 456;
    Predef$.MODULE$.println(v3 + v4);
  }

  public HowAreVarAndValImplementedInScala()
  {
    this.v1 = 123;
    this.v2 = 456;
  }
}

all public instance methods(exclude the constructor) are marked as override, why? is that necessary?

3 Scala compiler for .net looses the meaning of val

in the above c# code, we can see that v2 is just a normal field, while in the java couter part, v2 is marked as final, shouldn't v2 be marked as readonly by the Scala compiler for .net?(a bug?)

like image 445
Cui Pengfei 崔鹏飞 Avatar asked May 08 '13 14:05

Cui Pengfei 崔鹏飞


1 Answers

At the bytecode level, final doesn't exist for local variables. In fact the concept of local variables itself doesn't really exist either. Marking a local variable as final is purely for compile time checking. Since the information isn't present in the classfile, the decompiler has no way of guessing it.

As for the second two questions, I'm not as familiar with CIL bytecode, but if I had to guess I'd say that there's no reason not to add override, and readonly might have different semantics.

Edit: After looking through the CIL specification, here's what I've found.

The CIL equivalent of Java's final flag for fields is initonly, which appears to have the same semantics. It's not clear why the Scala compiler doesn't emit this. Perhaps they just didn't get around to it? Or perhaps the .net decompiler you used didn't reflect this. If you want to see what the compiler actually generates, you're best off looking at the bytecode directly.

like image 76
Antimony Avatar answered Nov 08 '22 17:11

Antimony