default initialization

479 views
Skip to first unread message

Dominik

unread,
Apr 25, 2012, 9:59:30 AM4/25/12
to scala-l...@googlegroups.com
I am surprised, that fields can be initialized with an underscore to their default value, but local variables can't:

class Foo {
  var foo:Int = _

  def bar = {
    var foo: Int = _ // Error: local variables must be initialized
    foo
  }
}

Any reason for this unequal treatment?
Dominik


Paul Phillips

unread,
Apr 25, 2012, 11:00:21 AM4/25/12
to scala-l...@googlegroups.com
On Wed, Apr 25, 2012 at 6:59 AM, Dominik <dominik...@fhnw.ch> wrote:
> Any reason for this unequal treatment?

I've never quite figured this one out. See
https://issues.scala-lang.org/browse/SI-4437 including the fact that
martin had a chance to endorse changing it; but that's a little
indirect to serve as an edict. I feel like if there were no objection
I'd have fixed this a long long time ago, but I can't remember.

martin odersky

unread,
Apr 25, 2012, 12:12:59 PM4/25/12
to scala-l...@googlegroups.com
It corresponds to the JVM. You can omit a field initialization but not a local variable initialization. Omitting local variable initializations means that the compiler has to be able to synthesize a default value for every type. That's not so easy in the face of type parameters, specialization, and so on. 

Cheers

 - Martin

Paul Phillips

unread,
Apr 25, 2012, 12:48:30 PM4/25/12
to scala-l...@googlegroups.com
On Wed, Apr 25, 2012 at 9:12 AM, martin odersky <martin....@epfl.ch> wrote:
> It corresponds to the JVM. You can omit a field initialization but not a
> local variable initialization. Omitting local variable initializations means
> that the compiler has to be able to synthesize a default value for every
> type. That's not so easy in the face of type parameters, specialization, and
> so on.

This seems like a distinction without a difference. We know what
happens if a field definition is omitted. We can do the same thing
for locals, even if it requires an instruction or something.

It's not like default field initialization has something so nice going on:

scala> class A { var x: NotNull = _ }
defined class A

scala> (new A).x
res0: NotNull = null

In practice, what everyone does is "null.asInstanceOf[T]". Which
works for everything, for the definition of "works" being sought -
being able to allocate a slot of a particular type. We could do it
for them. They would gain in safety this way, because right now
everybody blindly performs that cast, which will subvert any possible
safety; whereas if we synthesized it, we could at least bring some
minimal sanity like statically failing the compile if the local type
explicitly excludes Null. (Then they could still cast it.)

I feel like anytime the "best practice" way of doing something is
"null.asInstanceOf[T]" then it's time to reconsider the links of the
chain.

martin odersky

unread,
Apr 25, 2012, 1:21:15 PM4/25/12
to scala-l...@googlegroups.com
On Wed, Apr 25, 2012 at 6:48 PM, Paul Phillips <pa...@improving.org> wrote:
On Wed, Apr 25, 2012 at 9:12 AM, martin odersky <martin....@epfl.ch> wrote:
> It corresponds to the JVM. You can omit a field initialization but not a
> local variable initialization. Omitting local variable initializations means
> that the compiler has to be able to synthesize a default value for every
> type. That's not so easy in the face of type parameters, specialization, and
> so on.

This seems like a distinction without a difference.  We know what
happens if a field definition is omitted.  We can do the same thing
for locals, even if it requires an instruction or something.

In terms of bytecodes there IS a clear difference. The JVM will initialize object fields by default and require that local variables are initialized explicitly. I see your arguments, but I am not sure whether we should break a useful principle of Java (locals have to be initialized before being used), or whether we should rather go the full length and introduce flow-based initialization checking as in Java. That would be the better solution, IMO, but would require significant work in terms of spec and implementation. Faced with these choices my natural instinct is to do nothing for now :-)

Cheers

 - Martin


Dominik

unread,
Apr 25, 2012, 2:17:54 PM4/25/12
to scala-l...@googlegroups.com
The JVM will initialize object fields by default and require that local variables are initialized explicitly.

I was always thinking that with a declaration of a local variable
   var x: T = _
that variable IS actually initialized explicitly, and it could also implemented that way for locals without violating the JVM constraints and without having to implement definite assignment.

If I read the Scala-Spec correctly it only specifies that a variable with a _-initialization has a default initial value. It does not specify whether this initial value is given by the JVM or set with an explicit byte-code instruction.

Dominik

martin odersky

unread,
Apr 25, 2012, 2:31:22 PM4/25/12
to scala-l...@googlegroups.com
On Wed, Apr 25, 2012 at 8:17 PM, Dominik <dominik...@fhnw.ch> wrote:
The JVM will initialize object fields by default and require that local variables are initialized explicitly.

I was always thinking that with a declaration of a local variable
   var x: T = _
that variable IS actually initialized explicitly, and it could also implemented that way for locals without violating the JVM constraints and without having to implement definite assignment.

No, it isn't.  

If I read the Scala-Spec correctly it only specifies that a variable with a _-initialization has a default initial value. It does not specify whether this initial value is given by the JVM or set with an explicit byte-code instruction.

It's given by the JVM. But you are right this is an implementation detail.

 - Martin
 

Jan Vanek

unread,
Apr 25, 2012, 3:00:46 PM4/25/12
to scala-l...@googlegroups.com
Initially I thought allowing to initialize locals with _ clearly makes it more regular. Now I am not so sure. I thought _ stands more for "something missing/unknown" and not for "default", having vars in classes initialized with _ is (at least partially) aligned with that philosophy because it is something missing which is provided by JVM (implementation detail). I think that if it is allowed to initialize locals with _ than the next thing I might want is:

def foo(): T = {
   if (dont_know_lets_fall_back)
      _
   else
      result
}

Which, I think, is unacceptable. So, 50/50. Having default for T would/might be nice. null[T] comes to mind. When in classes, one has:

class X {
   var m: T = _
}

The T is specified. To write:

   var m = null[T]

is not much longer. I can't say, I really like it, but zero is not a keyword.

Regards,
Jan

√iktor Ҡlang

unread,
Apr 25, 2012, 3:30:26 PM4/25/12
to scala-l...@googlegroups.com

_:T

Reply all
Reply to author
Forward
0 new messages