How do you define a local var/val in the primary constructor in Scala?

ScalaScala Primary-Constructor

Scala Problem Overview


In Scala, a class's primary constructor has no explicit body, but is defined implicitly from the class body. How, then, does one distinguish between fields and local values (i.e. values local to the constructor method)?

For example, take the following code snippet, a modified form of some sample code from "Programming in Scala":

class R(n: Int, d: Int) {
   private val g = myfunc
   val x = n / g
   val y = d / g
}

My understanding is that this will generate a class with three fields: a private "g", and public "x" and "y". However, the g value is used only for calculation of the x and y fields, and has no meaning beyond the constructor scope.

So in this (admittedly artificial) example, how do you go about defining local values for this constructor?

Scala Solutions


Solution 1 - Scala

E.g.

class R(n: Int, d: Int) {
  val (x, y) = {
    val g = myfunc
    (n/g, d/g)
  }
}

Solution 2 - Scala

There are a few ways to do that. You can declare such temporary variables inside private definitions, to be used during construction time. You can use temporary variables inside blocks which return expressions (such as in Alaz's answer). Or, finally, you can use such variables inside alternate constructors.

In a manner similar to the alternate constructors, you could also define them inside the object-companion's "apply" method.

What you can't do is declare a field to be "temporary".

Note also that any parameter received by the primary constructor is a field also. If you don't want such parameters to become fields, and don't want to expose the actual fields in a constructor, the usual solution is to make the primary constructor private, with the actual fields, and use either an alternate constructor or an object-companion's apply() as the effective "primary" constructor.

Solution 3 - Scala

Another option we have is to make the primary object constructor private and use a companion object's apply method as a builder. If we apply (pun is not intended) this approach to your example it will look like this:

class R private (val x: Int, val y: Int);

object R {
  def apply(n: Int, d: Int): R = {
    val g = myfunc;
    new R(n / g, d / g);
  }
}

To create an R instance instead of:

val r = new R(1, 2);

write:

val r = R(1, 2);

This is a little bit verbose, but it could be worse, I think :). Let's hope that private[this] vals will be treated as temporary variables in future releases of Scala. Martin himself hinted that.

Solution 4 - Scala

Some discussion on this topic, including Martin Odersky's comments, is here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionskaffmanView Question on Stackoverflow
Solution 1 - ScalaAlexander AzarovView Answer on Stackoverflow
Solution 2 - ScalaDaniel C. SobralView Answer on Stackoverflow
Solution 3 - ScalaMaxim VladimirskyView Answer on Stackoverflow
Solution 4 - ScalaPavel FeldmanView Answer on Stackoverflow