Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala internals of var and val

Tags:

scala

What are the internal implementation of var and val in Scala? interested in knowing the details of their implementations- what makes var a "var" how mutable structure is implemented vs val (more final like) structure which makes it immutable.

like image 245
Vikas Pandya Avatar asked Dec 04 '22 07:12

Vikas Pandya


2 Answers

I'll answer by example, using scalac and javap.

First I create Test.scala:

class Test {
  val x = 1
  var y = 2
}

Compile it via scalac Test.scala to generate Test.class, then use javap -p Test.class to get

public class Test {
  private final int x;
  private int y;
  public int x();
  public int y();
  public void y_$eq(int);
  public Test();
}

So you can see that val x became a private final field on the class, and also a public final method to return that value.

var y became a non-final private field, and a getter+setter pair. The y_$eq(int) is the setter. In scala, that would be def y_=(newY: Int): Unit. Scala's syntax sugar will translate y = someValue into a call to y_=(someValue).

like image 144
Dylan Avatar answered Dec 06 '22 19:12

Dylan


You have to distinguish declarations (in a class template) from definitions (in a block, or in a template where they declare members and also form the constructor body)

A var decl is specified in section 4.2 to be equivalent to a getter/setter pair.

As an implementation detail, a val is just a getter.

Both members have a private backing field with a slightly mangled name: it has a trailing space.

There are a couple of anomalies, such as:

scala> class X { final val x = 7 }  // the underlying field is not initialized
defined class X

scala> :javap -prv X
{
[snip]
  private final int x;
    flags: ACC_PRIVATE, ACC_FINAL
[snip]
  public $line5.$read$$iw$$iw$X();
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0       
         1: invokespecial #14                 // Method java/lang/Object."<init>":()V
         4: return        

Material difference between template and block:

scala> class Y { def y = { var z = 0; def z_=(zz: Int): Unit = ???; z = 1; z } }

scala> class Y { var z = 0; def z_=(zz: Int): Unit = ???; z = 1 }
<console>:7: error: method z_= is defined twice

In the REPL, you are really making templates (because everything is wrapped in a class):

scala> var z = 0 ; def z_=(zz: Int): Unit = ???
<console>:7: error: method z_= is defined twice
  conflicting symbols both originated in file '<console>'
       var z = 0 ; def z_=(zz: Int): Unit = ???
                       ^

scala> { var z = 0 ; def z_=(zz: Int): Unit = ??? }
like image 31
som-snytt Avatar answered Dec 06 '22 19:12

som-snytt