What is the purpose of final val in Scala? [duplicate] - scala

What is the reason for vals not (?) being automatically final in singleton objects? E.g.
object NonFinal {
val a = 0
val b = 1
def test(i: Int) = (i: #annotation.switch) match {
case `a` => true
case `b` => false
}
}
results in:
<console>:12: error: could not emit switch for #switch annotated match
def test(i: Int) = (i: #annotation.switch) match {
^
Whereas
object Final {
final val a = 0
final val b = 1
def test(i: Int) = (i: #annotation.switch) match {
case `a` => true
case `b` => false
}
}
Compiles without warnings, so presumably generates the faster pattern matching table.
Having to add final seems pure annoying noise to me. Isn't an object final per se, and thus also its members?

This is addressed explicitly in the specification, and they are automatically final:
Members of final classes or objects are implicitly also final, so
the final modifier is generally redundant for them, too. Note, however, that
constant value definitions (§4.1) do require an explicit final modifier, even if
they are defined in a final class or object.
Your final-less example compiles without errors (or warnings) with 2.10-M7, so I'd assume that there's a problem with the #switch checking in earlier versions, and that the members are in fact final.
Update: Actually this is more curious than I expected—if we compile the following with either 2.9.2 or 2.10-M7:
object NonFinal {
val a = 0
}
object Final {
final val a = 0
}
javap does show a difference:
public final class NonFinal$ implements scala.ScalaObject {
public static final NonFinal$ MODULE$;
public static {};
public int a();
}
public final class Final$ implements scala.ScalaObject {
public static final Final$ MODULE$;
public static {};
public final int a();
}
You see the same thing even if the right-hand side of the value definitions isn't a constant expression.
So I'll leave my answer, but it's not conclusive.

You're not asking "why aren't they final", you're asking "why aren't they inlined." It just happens that final is how you cue the compiler that you want them inlined.
The reason they are not automatically inlined is separate compilation.
object A { final val x = 55 }
object B { def f = A.x }
When you compile this, B.f returns 55, literally:
public int f();
0: bipush 55
2: ireturn
That means if you recompile A, B will be oblivious to the change. If x is not marked final in A, B.f looks like this instead:
0: getstatic #19 // Field A$.MODULE$:LA$;
3: invokevirtual #22 // Method A$.x:()I
6: ireturn
Also, to correct one of the other answers, final does not mean immutable in scala.

To address the central question about final on an object, I think this clause from the spec is more relevant:
A constant value definition is of the form final val x = e
where e is a constant expression (§6.24). The final modifier must be present and no type annotation may be given. References to the constant value x are themselves treated as constant expressions; in the generated code they are replaced by the definition’s right-hand side e.
Of significance:
No type annotation may be given
The expression e is used in the generated code (by my reading, as the original unevaluated constant expression)
It sounds to me like the compiler is required by the spec to use these more like macro replacements rather than values that are evaluated in place at compile time, which could have impacts on how the resulting code runs.
I think it is particularly interesting that no type annotation may be given.
This, I think points to our ultimate answer, though I cannot come up with an example that shows the runtime difference for these requirements. In fact, in my 2.9.2 interpreter, I don't even get the enforcement of the first rule.

Related

Access scala variable by string name

I'm trying to access variables of an object by using strings whose values are determined at run time.
Basically the object is used as a dictionary, and now I want to dynamically poll values from that dictionary
A simplified example:
object Something extends scala.AnyRef {
final val zero = 0
final val one = 1
final val two = 2
}
I would then principally like to do the following
Somthing."zero"
and get 0 in return.
Ideally I would like to use scala reflection for this
WARNING: Please heed Jörg W Mittag's advice before following my answer:
Scala heavily prefers type-safe compile-time reflection. So, using
reflection in this way is not the Scala way. The Scala way would
probably be to use compile-time reflection to generate all those
pattern match cases
Using reflection Something.getClass.getDeclaredMethods.foreach(println) gives:
public final int example.Something$.zero()
public final int example.Something$.one()
public final int example.Something$.two()
so to get the names we can do
Something.getClass.getDeclaredMethods.map(_.getName) // Array(zero,one,two)
and to get the value
Something.getClass.getMethod("zero").invoke(Something) // 0
Defining the following implicit class
implicit class AccessMembersByReflectionName(something: Something.type) {
def get(name: String): AnyRef = {
Something.getClass.getMethod(name).invoke(Something)
}
}
cleans up the call site
Something.get("zero") // 0
As #n.m. already pointed, if you only want to retrieve values of the same type given an string key, you should use a Dictionary.
However, if for some reason you still need an object, you could accomplish something similar of what you want with this method.
Object Something {
val Zero: Int = 0
val One: Int = 1
val Three: Int = 3
def getValueByString(valName: String): Int = valName.toLowerCase match {
case "zero" => Zero
case "one" => One
case "three" => Three
}
}
EDIT
I just read that you can modify the object, you still can make a function that will receive the object and the valName as a string.

Eta-expansion on non-methods works for fields but not for local variables

The following code is pretty much self-explanatory:
class EtaExpansionOnNonMethods { // or object
val zero = 0
val zeroEta = zero _ // compiles: () => Int
def f {
val one = 1
val oneEta = one _ // compilation error
}
}
Error:(7, 18) _ must follow method; cannot follow Int
val oneEta = one _
^
Why is eta-expansion on an e.g. Int field allowed (resulting in () => Int) but not on an Int local variable (resulting in a compilation error)? I'm using version 2.11.7.
That's because val members are actually compiled down to getter/setter-like methods, for example running javap EtaExpansionOnNonMethods.class that you'd get from running scalac gives you:
E:\EtaExp>"C:\Program Files\Java\jdk1.8.0_51\bin\javap" EtaExpansionOnNonMethods.class
Compiled from "EtaExp.scala"
public class EtaExpansionOnNonMethods {
public int zero();
public EtaExpansionOnNonMethods();
}
Notice that if you were to declare the member as private[this] val zero = 0, which is compiled down to a final field, you'd get the exact same error you get when trying to eta-expand a local variable or value.
In the end, the general premise still holds: you can use eta-expansion on methods, even when those methods are not really explicit. :)

Why are `private val` and `private final val` different?

I used to think that private val and private final val are same, until I saw section 4.1 in Scala Reference:
A constant value definition is of the form
final val x = e
where e is a constant expression (§6.24). The final modifier must be present and no type annotation may be given. References to the constant value x are themselves treated as constant expressions; in the generated code they are replaced by the definition’s right-hand side e.
And I have written a test:
class PrivateVal {
private val privateVal = 0
def testPrivateVal = privateVal
private final val privateFinalVal = 1
def testPrivateFinalVal = privateFinalVal
}
javap -c output:
Compiled from "PrivateVal.scala"
public class PrivateVal {
public int testPrivateVal();
Code:
0: aload_0
1: invokespecial #19 // Method privateVal:()I
4: ireturn
public int testPrivateFinalVal();
Code:
0: iconst_1
1: ireturn
public PrivateVal();
Code:
0: aload_0
1: invokespecial #24 // Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_0
6: putfield #14 // Field privateVal:I
9: return
}
The byte code is just as Scala Reference said: private val is not private final val.
Why doesn't scalac just treat private val as private final val? Is there any underlying reason?
So, this is just a guess, but it was a perennial annoyance in Java that final static variables with a literal on the right-hand side get inlined into bytecode as constants. That engenders a performance benefit sure, but it causes binary compatibility of the definition to break if the "constant" ever changed. When defining a final static variable whose value might need to change, Java programmers have to resort to hacks like initializing the value with a method or constructor.
A val in Scala is already final in the Java sense. It looks like Scala's designers are using the redundant modifier final to mean "permission to inline the constant value". So Scala programmers have complete control over this behavior without resorting to hacks: if they want an inlined constant, a value that should never change but is fast, they write "final val". if they want flexibility to change the value without breaking binary compatibility, just "val".
I think the confusion here arises from conflating immutability with the semantics of final. vals can be overridden in child classes and therefore can't be treated as final unless marked as such explicitly.
#Brian The REPL provides class scope at the line level. See:
scala> $iw.getClass.getPackage
res0: Package = package $line3
scala> private val x = 5
<console>:5: error: value x cannot be accessed in object $iw
lazy val $result = `x`
scala> private val x = 5; println(x);
5

Twitter says Scala can't emit a raw unvarnished volatile field. True?

The fine Twitter util library has the following Java class, which is extended by a Scala class that reads the volatile field and updates it using AtomicReferenceFieldUpdater. Access must be at least private, i.e., must allow other.state.
Is the motivational claim in the comment true? How true? ("How" means in what way and to what degree.)
public class IVarField<A> {
/** This is needed because we cannot create a field like this in Scala. */
volatile State<A> state;
}
Something like the following works.
Making the field "private [this]" turns it into the desired field reference ("getfield").
Access from a different instance is through an accessor "state()" which, if made #inline, will happily loosen the access restriction to the field.
That also means that the updater (which happens to reside in the companion module) can also access it.
(Because the normal accessor for the var is not emitted for an object-private member, you can define your own, using parens. But you don't need to use parens at the call site, other.state. Your uniform access principle dollars at work. Or Swiss francs.)
Also notice the totally hip usage of `new` in backticks for a param name. I don't even know how to make the ticks show up in this markup. Because both params are the same type, one is likely to want to write cas(expect=prev, `new`=changed), so I might have used next instead, but if this markup supported a hipster thumbs-up, I'd give it right now. :+1: Did it work? Can anyone see my thumb? [I guess I saw that on github. Hubster, not hipster.]
object IVar {
// TODO: retrieve mangled name by reflection
private final val stateField = "com$twitter$concurrent$IVar$$state"
private val stateUpd = AtomicReferenceFieldUpdater.newUpdater(
classOf[IVar[_]], classOf[State[_]], stateField)
}
final class IVar[A] { //}extends IVarField[A] {
import IVar._
#volatile private[this] var state: State[A] = initState: State[A]
#inline private final def state(): State[A] = this.state
override def toString = "Ivar#%s(state=%s)".format(hashCode, state)
#inline private[this]
def cas(expect: State[A], `new`: State[A]) = stateUpd.compareAndSet(this, expect, `new`)
def depth: Int = {
#tailrec
def loop(iv: IVar[_], d: Int): Int = iv.state match {
case Linked(iv) => loop(iv, d + 1)
case _ => d
}
loop(this, 0)
}
// etc
}
Showing that state() is really inlined:
private final int loop$1(com.twitter.concurrent.IVar, int);
flags: ACC_PRIVATE, ACC_FINAL
Code:
stack=3, locals=5, args_size=3
0: aload_1
// Field com$twitter$concurrent$IVar$$state:Lcom/twitter/concurrent/ivar/State;
1: getfield #16
4: astore_3
Not only is it "OK to ask and answer your own questions",
https://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/
it's infinitely more satisfying.
(More power to Daniel Sobral, Rex Kerr, Retronym and the rest of the Justice League.)

Scala class members and constructor parameters name clash

Consider the following class written in Java:
class NonNegativeDouble {
private final double value;
public NonNegativeDouble(double value) {
this.value = Math.abs(value);
}
public double getValue() { return value; }
}
It defines a final field called value that is initialized in the constructor, by taking its parameter called alike and applying a function to it.
I want to write something similar to it in Scala. At first, I tried:
class NonNegativeDouble(value: Double) {
def value = Math.abs(value)
}
But the compiler complains: error: overloaded method value needs result type
Obviously the compiler thinks that the expression value inside the expression Math.abs(value) refers to the method being defined. Therefore, the method being defined is recursive, so I need to state its return type. So, the code I wrote does not do what I expected it to do: I wanted value inside Math.abs(value) to refer to the constructor parameter value, and not to the method being defined. It is as if the compiler implicitly added a this. to Math.abs(this.value).
Adding val or var (or private ... variants) to the constructor parameter doesn't seem to help.
So, my question is: can I define a property with the same name as a constructor parameter, but maybe a different value? If so, how? If not, why?
Thanks!
No, you can't. In Scala, constructor parameters are properties, so it makes no sense to redefine them.
The solution, naturally, is to use another name:
class NonNegativeDouble(initValue: Double) {
val value = Math.abs(initValue)
}
Used like this, initValue won't be part of the instances created. However, if you use it in a def or a pattern matching declaration, then it becomes a part of every instance of the class.
#Daniel C. Sobral
class NonNegativeDouble(initValue: Double) {
val value = Math.abs(initValue)
}
your code is right, but "constructor parameters are properties",this is not true.
A post from the official site said,
A parameter such as class Foo(x : Int) is turned into a field if it is
referenced in one or more methods
And Martin's reply confirms its truth:
That's all true, but it should be treated as an implementation
technique. That's why the spec is silent about it.
So normally, we can still treat primary constructor parameters as normal method parameter, but when the parameters is referenced by any of the methods, the compiler will cleverly turn it into a private field.
If any formal parameter preceded by the val, the compiler generates an getter definition automatically.if var, generates a setter additionally. see the language speification section 5.3.
That's all about primary constructor parameters.
You can consider parametric field
class NonNegativeDouble(val value: Double, private val name: String ){
if (value < 0) throw new IllegalArgumentException("value cannot be negative")
override def toString =
"NonNegativeDouble(value = %s, name = %s)" format (value, name)
}
val tom = "Tom"
val k = -2.3
val a = new NonNegativeDouble(k.abs, tom)
a: NonNegativeDouble = NonNegativeDouble(value = 2.3, name = Tom)
a.value
res13: Double = 2.3
a.name
<console>:12: error: value name in class NonNegativeDouble cannot be accessed in NonNegativeDouble
a.name
val b = new NonNegativeDouble(k, tom)
java.lang.IllegalArgumentException: value cannot be negative
...
It's defines fields and parameters with the same names "value", "name".
You can add modifiers such as private ...
In the case of case classes it should be:
case class NonNegativeDouble(private val initValue: Double) {
val value = Math.abs(initValue)
def copy(value: Double = this.value) = NonNegativeDouble(value)
}
The implementation of copy is required to prevent the sintesized version of the compiler that will bind the initValue argument.
I expect that the compiler is smart enough to not retain the «extra space» for the initValue. I haven't verified this behaviour.