Description
An obscure use of _
occurs in var
definitions:
var x: T = _
It defines a concrete variable x
without an initial value, or rather the default initial value that the JVM assigns to object fields. It can only be used in a class or object, not to initialize a local variable. It is essential in situations like this:
new AbstractIterator[A] {
private[this] var hd: A = _
private[this] var hdDefined: Boolean = false
...
}
Here we cannot initialize hd
with a value since its type is parametric, and we do not know a value for A
. The logic in AbstractIterator
makes sure that hd
is read only after it is assigned by checking hdDefined
before reading hd
.
So the idiom is rare but essential where it is needed. But can we find a less obscure notation that does not add another overload to _
?
One possibility would be to define somewhere an abstraction like this:
def defaultValue[T]: T = ...
defaultValue
can be expressed in terms of _
:
def defaultValue[T]: T =
object helper { var x: T = _ }
helper.x
It can also be a compiler-intrinsic, and then it could replace = _
in variable definitions.
But I am a bit reluctant to do that, for fear that then defaultValue
will be also used in situations where it is not appropriate. The big problem with defaultValue
is that it returns null
for all class types including boxed numeric types. That's very confusing! We do not want to give this a more prominent status than what we have. The situation would get worse with explicit nulls. In that case, we would have:
def defaultValue[T]: T | Null
But then
var x: T = defaultValue
would be ill-typed. It would have to be:
var x: T | Null = defaultValue
This is safe, but it defeats the purpose. What should happen for
var x: T = _
is that the programmer or the init-checker proves that x
will be initialized with something else before it is first referenced. That's the intended meaning.
So, maybe a better choice is to re-use compiletime.erasedValue
for this?
var x: T = erasedValue
This means there is no initial value at runtime (the value is erased), so there is no initial assignment. That can be allowed for objects and classes since objects are bulk-initialized (but the init checker should check that such variables are not referenced before being assigned to). It could be allowed in the future also for local variables if we can prove that the variable is initialized by assignment before use. Everywhere else erasedValue
is illegal, by the current rules.
Admittedly, erasedValue
is also obscure. However
- The whole thing is an obscure use case
erasedValue
can be looked up, unlike_
erasedValue
does not add to the confusion relative to the other uses of_
.