Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding explicit type to val prevents val from being used as a constant in annotation

From the REPL:

scala> final val x = "x"
x: java.lang.String("x") = x

scala> @javax.persistence.Table(name = x) case class foo()
defined class foo

scala> final val x:java.lang.String = "x"
x: java.lang.String = x

scala> @javax.persistence.Table(name = x) case class foo()
<console>:6: error: annotation argument needs to be a constant; found: x
       @javax.persistence.Table(name = x) case class foo()

Can someone explain why this only works without a type?

like image 529
scalapeno Avatar asked Jul 28 '11 18:07

scalapeno


1 Answers

Without the type, final val acts like a literal constant -- the identifier is replaced by its value at compile time. With the type, it becomes a reference to something stored somewhere, which cannot be used on annotations.

This is defined on section 4.1 of the specification:

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.

This is the only way you can get true named constants in Scala. They have performance benefits, they are really guaranteed not to mutate (even a final val with a type can be changed through reflection) and, of course, they can be used in annotations.

like image 199
Daniel C. Sobral Avatar answered Nov 15 '22 20:11

Daniel C. Sobral