Discussion:
val initialization semantic is counterintuitive
Eugen Labun
2011-03-22 15:14:16 UTC
Permalink
Hi all,

eventually (or even surely) this is an old question but I haven't found an explanation for this
simple situation (nor in Language Specification, nor in Scala-Book).

(More complicated cases are described in this excellent faq from Paul:
https://github.com/paulp/scala-faq/wiki/Initialization-Order)


Constructions like

def m {
val x = y // compile error "forward reference extends over definition of value x"
val y = 5
}

cause a compile error if used in methods,
but are accepted in constructors/initializers:

class/object T {
val x = y // compiles OK, x = 0
val y = 5
}

The 'x' in the code above gets initialized to 0 (!), not to 5.


Both -- acceptance by the compiler and initialization to 0 -- are counterintuitive to me.
Would a compile error for the second case ("illegal forward reference") not be a more preferable?


I'm aware of '-Xcheckinit' compiler option. But this introduces only *runtime* check and doesn't
prevent the code to compile.


There was a ticket https://lampsvn.epfl.ch/trac/scala/ticket/399, but it's closed. I cannot
understand the reason of closing (it cites one more example of such counterintuitive behavior but
doesn't explain why this behavior can't be changed).


Java handles a semantically analogous situation as expected:

class C {
final int a = 3;
{
System.out.println("a: " + a); // OK
System.out.println("y: " + y); // Error: illegal forward reference
}
final int x = y; // Error: illegal forward reference
final int y = 5;

public static void main(String[] args) {
// final int x = y; // Error: cannot find symbol variable y
final int y = 5;
}
}


I understand that Scala vals do not map 1:1 to Java final variables, and that generating bytecode
from Scala code is much more complicated (having in mind such things as unified access principle and
therefore introducing methods for vals/vars, mapping of Scala's primary constructor to constructors
and initializers in Java, inheritance and overriding val->def->var, ...)

But, despite how complicated can be the generated code, hopefully, might it be possible to detect
such forward references in Scala parser and generate an error?


--
Regards,
Eugen
Sofoklis Papasofokli
2016-09-09 23:42:31 UTC
Permalink
Hi,

Strange that nobody commented on this one for so long.

I know its an old thread but i keep getting issues from this, I also
believe there should be a compiler error in this situation, its totally
unexpected behavior.

Best Regards,
Sofoklis
Post by Eugen Labun
Hi all,
eventually (or even surely) this is an old question but I haven't found an
explanation for this
simple situation (nor in Language Specification, nor in Scala-Book).
https://github.com/paulp/scala-faq/wiki/Initialization-Order)
Constructions like
def m {
val x = y // compile error "forward reference extends over definition of value x"
val y = 5
}
cause a compile error if used in methods,
class/object T {
val x = y // compiles OK, x = 0
val y = 5
}
The 'x' in the code above gets initialized to 0 (!), not to 5.
Both -- acceptance by the compiler and initialization to 0 -- are counterintuitive to me.
Would a compile error for the second case ("illegal forward reference")
not be a more preferable?
I'm aware of '-Xcheckinit' compiler option. But this introduces only
*runtime* check and doesn't
prevent the code to compile.
There was a ticket https://lampsvn.epfl.ch/trac/scala/ticket/399, but it's closed. I cannot
understand the reason of closing (it cites one more example of such
counterintuitive behavior but
doesn't explain why this behavior can't be changed).
class C {
final int a = 3;
{
System.out.println("a: " + a); // OK
System.out.println("y: " + y); // Error: illegal forward reference
}
final int x = y; // Error: illegal forward reference
final int y = 5;
public static void main(String[] args) {
// final int x = y; // Error: cannot find symbol variable y
final int y = 5;
}
}
I understand that Scala vals do not map 1:1 to Java final variables, and
that generating bytecode
from Scala code is much more complicated (having in mind such things as
unified access principle and
therefore introducing methods for vals/vars, mapping of Scala's primary
constructor to constructors
and initializers in Java, inheritance and overriding val->def->var, ...)
But, despite how complicated can be the generated code, hopefully, might
it be possible to detect
such forward references in Scala parser and generate an error?
--
Regards,
Eugen
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
martin odersky
2016-09-10 20:43:42 UTC
Permalink
I think that's a suggestion worth considering! In general it is extremely
hard to detect uninitialized fields statically. But a scheme of disallowing
direct forward references is easy to do and catches the most obvious bugs.

Cheers

- Martin
Post by Sofoklis Papasofokli
Hi,
Strange that nobody commented on this one for so long.
I know its an old thread but i keep getting issues from this, I also
believe there should be a compiler error in this situation, its totally
unexpected behavior.
Best Regards,
Sofoklis
Post by Eugen Labun
Hi all,
eventually (or even surely) this is an old question but I haven't found
an explanation for this
simple situation (nor in Language Specification, nor in Scala-Book).
https://github.com/paulp/scala-faq/wiki/Initialization-Order)
Constructions like
def m {
val x = y // compile error "forward reference extends over definition of value x"
val y = 5
}
cause a compile error if used in methods,
class/object T {
val x = y // compiles OK, x = 0
val y = 5
}
The 'x' in the code above gets initialized to 0 (!), not to 5.
Both -- acceptance by the compiler and initialization to 0 -- are counterintuitive to me.
Would a compile error for the second case ("illegal forward reference")
not be a more preferable?
I'm aware of '-Xcheckinit' compiler option. But this introduces only
*runtime* check and doesn't
prevent the code to compile.
There was a ticket https://lampsvn.epfl.ch/trac/scala/ticket/399, but
it's closed. I cannot
understand the reason of closing (it cites one more example of such
counterintuitive behavior but
doesn't explain why this behavior can't be changed).
class C {
final int a = 3;
{
System.out.println("a: " + a); // OK
System.out.println("y: " + y); // Error: illegal forward reference
}
final int x = y; // Error: illegal forward reference
final int y = 5;
public static void main(String[] args) {
// final int x = y; // Error: cannot find symbol variable y
final int y = 5;
}
}
I understand that Scala vals do not map 1:1 to Java final variables, and
that generating bytecode
from Scala code is much more complicated (having in mind such things as
unified access principle and
therefore introducing methods for vals/vars, mapping of Scala's primary
constructor to constructors
and initializers in Java, inheritance and overriding val->def->var, ...)
But, despite how complicated can be the generated code, hopefully, might
it be possible to detect
such forward references in Scala parser and generate an error?
--
Regards,
Eugen
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
Martin Odersky
EPFL and Lightbend
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Adriaan Moors
2016-09-11 08:37:41 UTC
Permalink
Val initialization is confusing, I agree, but note that you do get a
warning. I'm a bit concerned about making this an error as you could
override `val x` in a subclass (it's still weird, but should it be an
error?).

Welcome to Scala 2.12.0-RC1 (Java HotSpot(TM) 64-Bit Server VM, Java
1.8.0_102).
Type in expressions for evaluation. Or try :help.

scala> class T {
| val x = y // compiles OK, x = 0
| val y = 5
| }
*<console>:12: warning: Reference to uninitialized value y*
val x = y // compiles OK, x = 0
^
Post by martin odersky
I think that's a suggestion worth considering! In general it is extremely
hard to detect uninitialized fields statically. But a scheme of disallowing
direct forward references is easy to do and catches the most obvious bugs.
Cheers
- Martin
On Sat, Sep 10, 2016 at 1:42 AM, Sofoklis Papasofokli <
Post by Sofoklis Papasofokli
Hi,
Strange that nobody commented on this one for so long.
I know its an old thread but i keep getting issues from this, I also
believe there should be a compiler error in this situation, its totally
unexpected behavior.
Best Regards,
Sofoklis
Post by Eugen Labun
Hi all,
eventually (or even surely) this is an old question but I haven't found
an explanation for this
simple situation (nor in Language Specification, nor in Scala-Book).
https://github.com/paulp/scala-faq/wiki/Initialization-Order)
Constructions like
def m {
val x = y // compile error "forward reference extends over definition of value x"
val y = 5
}
cause a compile error if used in methods,
class/object T {
val x = y // compiles OK, x = 0
val y = 5
}
The 'x' in the code above gets initialized to 0 (!), not to 5.
Both -- acceptance by the compiler and initialization to 0 -- are
counterintuitive to me.
Would a compile error for the second case ("illegal forward reference")
not be a more preferable?
I'm aware of '-Xcheckinit' compiler option. But this introduces only
*runtime* check and doesn't
prevent the code to compile.
There was a ticket https://lampsvn.epfl.ch/trac/scala/ticket/399, but
it's closed. I cannot
understand the reason of closing (it cites one more example of such
counterintuitive behavior but
doesn't explain why this behavior can't be changed).
class C {
final int a = 3;
{
System.out.println("a: " + a); // OK
System.out.println("y: " + y); // Error: illegal forward reference
}
final int x = y; // Error: illegal forward reference
final int y = 5;
public static void main(String[] args) {
// final int x = y; // Error: cannot find symbol variable y
final int y = 5;
}
}
I understand that Scala vals do not map 1:1 to Java final variables, and
that generating bytecode
from Scala code is much more complicated (having in mind such things as
unified access principle and
therefore introducing methods for vals/vars, mapping of Scala's primary
constructor to constructors
and initializers in Java, inheritance and overriding val->def->var, ...)
But, despite how complicated can be the generated code, hopefully, might
it be possible to detect
such forward references in Scala parser and generate an error?
--
Regards,
Eugen
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
Martin Odersky
EPFL and Lightbend
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Sébastien Doeraene
2016-09-11 08:53:33 UTC
Permalink
Hello,

Fun fact: we even have a test in Scala.js that makes sure that it behaves
like that even for Scala.js-defined JS classes ^^
https://github.com/scala-js/scala-js/blob/v0.6.12/test-suite/js/src/test/scala/org/scalajs/testsuite/jsinterop/ScalaJSDefinedTest.scala#L359-L367

Btw, indeed, this is one of the 5 warnings that we get when compiling our
test suite (not counting deprecation warnings):

[warn] .../ScalaJSDefinedTest.scala:361: Reference to uninitialized value y
[warn] val x = y
[warn] ^

Cheers,
Sébastien
Post by Adriaan Moors
Val initialization is confusing, I agree, but note that you do get a
warning. I'm a bit concerned about making this an error as you could
override `val x` in a subclass (it's still weird, but should it be an
error?).
Welcome to Scala 2.12.0-RC1 (Java HotSpot(TM) 64-Bit Server VM, Java
1.8.0_102).
Type in expressions for evaluation. Or try :help.
scala> class T {
| val x = y // compiles OK, x = 0
| val y = 5
| }
*<console>:12: warning: Reference to uninitialized value y*
val x = y // compiles OK, x = 0
^
Post by martin odersky
I think that's a suggestion worth considering! In general it is extremely
hard to detect uninitialized fields statically. But a scheme of disallowing
direct forward references is easy to do and catches the most obvious bugs.
Cheers
- Martin
On Sat, Sep 10, 2016 at 1:42 AM, Sofoklis Papasofokli <
Post by Sofoklis Papasofokli
Hi,
Strange that nobody commented on this one for so long.
I know its an old thread but i keep getting issues from this, I also
believe there should be a compiler error in this situation, its totally
unexpected behavior.
Best Regards,
Sofoklis
Post by Eugen Labun
Hi all,
eventually (or even surely) this is an old question but I haven't found
an explanation for this
simple situation (nor in Language Specification, nor in Scala-Book).
https://github.com/paulp/scala-faq/wiki/Initialization-Order)
Constructions like
def m {
val x = y // compile error "forward reference extends over definition of value x"
val y = 5
}
cause a compile error if used in methods,
class/object T {
val x = y // compiles OK, x = 0
val y = 5
}
The 'x' in the code above gets initialized to 0 (!), not to 5.
Both -- acceptance by the compiler and initialization to 0 -- are
counterintuitive to me.
Would a compile error for the second case ("illegal forward reference")
not be a more preferable?
I'm aware of '-Xcheckinit' compiler option. But this introduces only
*runtime* check and doesn't
prevent the code to compile.
There was a ticket https://lampsvn.epfl.ch/trac/scala/ticket/399, but
it's closed. I cannot
understand the reason of closing (it cites one more example of such
counterintuitive behavior but
doesn't explain why this behavior can't be changed).
class C {
final int a = 3;
{
System.out.println("a: " + a); // OK
System.out.println("y: " + y); // Error: illegal forward reference
}
final int x = y; // Error: illegal forward reference
final int y = 5;
public static void main(String[] args) {
// final int x = y; // Error: cannot find symbol variable y
final int y = 5;
}
}
I understand that Scala vals do not map 1:1 to Java final variables,
and that generating bytecode
from Scala code is much more complicated (having in mind such things as
unified access principle and
therefore introducing methods for vals/vars, mapping of Scala's primary
constructor to constructors
and initializers in Java, inheritance and overriding val->def->var, ...)
But, despite how complicated can be the generated code, hopefully,
might it be possible to detect
such forward references in Scala parser and generate an error?
--
Regards,
Eugen
--
You received this message because you are subscribed to the Google
Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send
For more options, visit https://groups.google.com/d/optout.
--
Martin Odersky
EPFL and Lightbend
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
martin odersky
2016-09-11 09:42:45 UTC
Permalink
Post by Sébastien Doeraene
Hello,
Fun fact: we even have a test in Scala.js that makes sure that it behaves
like that even for Scala.js-defined JS classes ^^
https://github.com/scala-js/scala-js/blob/v0.6.12/test-
suite/js/src/test/scala/org/scalajs/testsuite/jsinterop/
ScalaJSDefinedTest.scala#L359-L367
Btw, indeed, this is one of the 5 warnings that we get when compiling our
[warn] .../ScalaJSDefinedTest.scala:361: Reference to uninitialized value y
[warn] val x = y
[warn] ^
Was that a real failure, or just a test to exercise this specifically?
Cheers

- Martin
Post by Sébastien Doeraene
Cheers,
Sébastien
Post by Adriaan Moors
Val initialization is confusing, I agree, but note that you do get a
warning. I'm a bit concerned about making this an error as you could
override `val x` in a subclass (it's still weird, but should it be an
error?).
Welcome to Scala 2.12.0-RC1 (Java HotSpot(TM) 64-Bit Server VM, Java
1.8.0_102).
Type in expressions for evaluation. Or try :help.
scala> class T {
| val x = y // compiles OK, x = 0
| val y = 5
| }
*<console>:12: warning: Reference to uninitialized value y*
val x = y // compiles OK, x = 0
^
Post by martin odersky
I think that's a suggestion worth considering! In general it is
extremely hard to detect uninitialized fields statically. But a scheme of
disallowing direct forward references is easy to do and catches the most
obvious bugs.
Cheers
- Martin
On Sat, Sep 10, 2016 at 1:42 AM, Sofoklis Papasofokli <
Post by Sofoklis Papasofokli
Hi,
Strange that nobody commented on this one for so long.
I know its an old thread but i keep getting issues from this, I also
believe there should be a compiler error in this situation, its totally
unexpected behavior.
Best Regards,
Sofoklis
Post by Eugen Labun
Hi all,
eventually (or even surely) this is an old question but I haven't
found an explanation for this
simple situation (nor in Language Specification, nor in Scala-Book).
https://github.com/paulp/scala-faq/wiki/Initialization-Order)
Constructions like
def m {
val x = y // compile error "forward reference extends over
definition of value x"
val y = 5
}
cause a compile error if used in methods,
class/object T {
val x = y // compiles OK, x = 0
val y = 5
}
The 'x' in the code above gets initialized to 0 (!), not to 5.
Both -- acceptance by the compiler and initialization to 0 -- are
counterintuitive to me.
Would a compile error for the second case ("illegal forward
reference") not be a more preferable?
I'm aware of '-Xcheckinit' compiler option. But this introduces only
*runtime* check and doesn't
prevent the code to compile.
There was a ticket https://lampsvn.epfl.ch/trac/scala/ticket/399, but
it's closed. I cannot
understand the reason of closing (it cites one more example of such
counterintuitive behavior but
doesn't explain why this behavior can't be changed).
class C {
final int a = 3;
{
System.out.println("a: " + a); // OK
System.out.println("y: " + y); // Error: illegal forward reference
}
final int x = y; // Error: illegal forward reference
final int y = 5;
public static void main(String[] args) {
// final int x = y; // Error: cannot find symbol variable y
final int y = 5;
}
}
I understand that Scala vals do not map 1:1 to Java final variables,
and that generating bytecode
from Scala code is much more complicated (having in mind such things
as unified access principle and
therefore introducing methods for vals/vars, mapping of Scala's
primary constructor to constructors
and initializers in Java, inheritance and overriding val->def->var, ...)
But, despite how complicated can be the generated code, hopefully,
might it be possible to detect
such forward references in Scala parser and generate an error?
--
Regards,
Eugen
--
You received this message because you are subscribed to the Google
Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send
For more options, visit https://groups.google.com/d/optout.
--
Martin Odersky
EPFL and Lightbend
--
You received this message because you are subscribed to the Google
Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
Martin Odersky
EPFL and Lightbend
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Sébastien Doeraene
2016-09-11 10:02:48 UTC
Permalink
It's just a test to exercise this specifically. It was added at the exact
same time we implemented Scala.js-defined JS classes, so there never was a
(committed) bug.

For Scala.js-defined JS classes, the object initialization scheme is,
implementation-wise, significantly different from the one used for Scala
classes. Hence we have tests for known corner-cases of Scala initialization
order, to make sure we're (bug-)compatible.

Cheers,
Sébastien
On Sun, Sep 11, 2016 at 10:53 AM, Sébastien Doeraene <
Post by Sébastien Doeraene
Hello,
Fun fact: we even have a test in Scala.js that makes sure that it behaves
like that even for Scala.js-defined JS classes ^^
https://github.com/scala-js/scala-js/blob/v0.6.12/test-suite
/js/src/test/scala/org/scalajs/testsuite/jsinterop/ScalaJSDe
finedTest.scala#L359-L367
Btw, indeed, this is one of the 5 warnings that we get when compiling our
[warn] .../ScalaJSDefinedTest.scala:361: Reference to uninitialized value y
[warn] val x = y
[warn] ^
Was that a real failure, or just a test to exercise this specifically?
Cheers
- Martin
Post by Sébastien Doeraene
Cheers,
Sébastien
Post by Adriaan Moors
Val initialization is confusing, I agree, but note that you do get a
warning. I'm a bit concerned about making this an error as you could
override `val x` in a subclass (it's still weird, but should it be an
error?).
Welcome to Scala 2.12.0-RC1 (Java HotSpot(TM) 64-Bit Server VM, Java
1.8.0_102).
Type in expressions for evaluation. Or try :help.
scala> class T {
| val x = y // compiles OK, x = 0
| val y = 5
| }
*<console>:12: warning: Reference to uninitialized value y*
val x = y // compiles OK, x = 0
^
Post by martin odersky
I think that's a suggestion worth considering! In general it is
extremely hard to detect uninitialized fields statically. But a scheme of
disallowing direct forward references is easy to do and catches the most
obvious bugs.
Cheers
- Martin
On Sat, Sep 10, 2016 at 1:42 AM, Sofoklis Papasofokli <
Post by Sofoklis Papasofokli
Hi,
Strange that nobody commented on this one for so long.
I know its an old thread but i keep getting issues from this, I also
believe there should be a compiler error in this situation, its totally
unexpected behavior.
Best Regards,
Sofoklis
Post by Eugen Labun
Hi all,
eventually (or even surely) this is an old question but I haven't
found an explanation for this
simple situation (nor in Language Specification, nor in Scala-Book).
https://github.com/paulp/scala-faq/wiki/Initialization-Order)
Constructions like
def m {
val x = y // compile error "forward reference extends over
definition of value x"
val y = 5
}
cause a compile error if used in methods,
class/object T {
val x = y // compiles OK, x = 0
val y = 5
}
The 'x' in the code above gets initialized to 0 (!), not to 5.
Both -- acceptance by the compiler and initialization to 0 -- are
counterintuitive to me.
Would a compile error for the second case ("illegal forward
reference") not be a more preferable?
I'm aware of '-Xcheckinit' compiler option. But this introduces only
*runtime* check and doesn't
prevent the code to compile.
There was a ticket https://lampsvn.epfl.ch/trac/scala/ticket/399,
but it's closed. I cannot
understand the reason of closing (it cites one more example of such
counterintuitive behavior but
doesn't explain why this behavior can't be changed).
class C {
final int a = 3;
{
System.out.println("a: " + a); // OK
System.out.println("y: " + y); // Error: illegal forward reference
}
final int x = y; // Error: illegal forward reference
final int y = 5;
public static void main(String[] args) {
// final int x = y; // Error: cannot find symbol variable y
final int y = 5;
}
}
I understand that Scala vals do not map 1:1 to Java final variables,
and that generating bytecode
from Scala code is much more complicated (having in mind such things
as unified access principle and
therefore introducing methods for vals/vars, mapping of Scala's
primary constructor to constructors
and initializers in Java, inheritance and overriding val->def->var, ...)
But, despite how complicated can be the generated code, hopefully,
might it be possible to detect
such forward references in Scala parser and generate an error?
--
Regards,
Eugen
--
You received this message because you are subscribed to the Google
Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send
For more options, visit https://groups.google.com/d/optout.
--
Martin Odersky
EPFL and Lightbend
--
You received this message because you are subscribed to the Google
Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google
Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
Martin Odersky
EPFL and Lightbend
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Sofoklis Papasofokli
2016-09-11 13:34:27 UTC
Permalink
Hi Adriaan,

Indeed you get a warning, i have a slightly different case minimized bellow
that has no warning or error:

object Ts {
def gety = y
val x = gety // compiles OK and no warning, x = 0
val y = 5
}
Post by Adriaan Moors
Val initialization is confusing, I agree, but note that you do get a
warning. I'm a bit concerned about making this an error as you could
override `val x` in a subclass (it's still weird, but should it be an
error?).
Welcome to Scala 2.12.0-RC1 (Java HotSpot(TM) 64-Bit Server VM, Java
1.8.0_102).
Type in expressions for evaluation. Or try :help.
scala> class T {
| val x = y // compiles OK, x = 0
| val y = 5
| }
*<console>:12: warning: Reference to uninitialized value y*
val x = y // compiles OK, x = 0
^
Post by martin odersky
I think that's a suggestion worth considering! In general it is extremely
hard to detect uninitialized fields statically. But a scheme of disallowing
direct forward references is easy to do and catches the most obvious bugs.
Cheers
- Martin
Post by Sofoklis Papasofokli
Hi,
Strange that nobody commented on this one for so long.
I know its an old thread but i keep getting issues from this, I also
believe there should be a compiler error in this situation, its totally
unexpected behavior.
Best Regards,
Sofoklis
Post by Eugen Labun
Hi all,
eventually (or even surely) this is an old question but I haven't found
an explanation for this
simple situation (nor in Language Specification, nor in Scala-Book).
https://github.com/paulp/scala-faq/wiki/Initialization-Order)
Constructions like
def m {
val x = y // compile error "forward reference extends over definition of value x"
val y = 5
}
cause a compile error if used in methods,
class/object T {
val x = y // compiles OK, x = 0
val y = 5
}
The 'x' in the code above gets initialized to 0 (!), not to 5.
Both -- acceptance by the compiler and initialization to 0 -- are
counterintuitive to me.
Would a compile error for the second case ("illegal forward reference")
not be a more preferable?
I'm aware of '-Xcheckinit' compiler option. But this introduces only
*runtime* check and doesn't
prevent the code to compile.
There was a ticket https://lampsvn.epfl.ch/trac/scala/ticket/399, but
it's closed. I cannot
understand the reason of closing (it cites one more example of such
counterintuitive behavior but
doesn't explain why this behavior can't be changed).
class C {
final int a = 3;
{
System.out.println("a: " + a); // OK
System.out.println("y: " + y); // Error: illegal forward reference
}
final int x = y; // Error: illegal forward reference
final int y = 5;
public static void main(String[] args) {
// final int x = y; // Error: cannot find symbol variable y
final int y = 5;
}
}
I understand that Scala vals do not map 1:1 to Java final variables,
and that generating bytecode
from Scala code is much more complicated (having in mind such things as
unified access principle and
therefore introducing methods for vals/vars, mapping of Scala's primary
constructor to constructors
and initializers in Java, inheritance and overriding val->def->var, ...)
But, despite how complicated can be the generated code, hopefully,
might it be possible to detect
such forward references in Scala parser and generate an error?
--
Regards,
Eugen
--
You received this message because you are subscribed to the Google
Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send
For more options, visit https://groups.google.com/d/optout.
--
Martin Odersky
EPFL and Lightbend
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Viktor Klang
2016-09-11 13:44:16 UTC
Permalink
Hi Sofoklis,
Post by Sofoklis Papasofokli
Hi Adriaan,
Indeed you get a warning, i have a slightly different case minimized
object Ts {
def gety = y
val x = gety // compiles OK and no warning, x = 0
val y = 5
}
public class Ts {
final int x;
final int y;
public Ts() {
x = gety(); // compiles OK and no warning, x = 0
y = 5;
}
private int gety() { return y; }
}
Post by Sofoklis Papasofokli
Post by Adriaan Moors
Val initialization is confusing, I agree, but note that you do get a
warning. I'm a bit concerned about making this an error as you could
override `val x` in a subclass (it's still weird, but should it be an
error?).
Welcome to Scala 2.12.0-RC1 (Java HotSpot(TM) 64-Bit Server VM, Java
1.8.0_102).
Type in expressions for evaluation. Or try :help.
scala> class T {
| val x = y // compiles OK, x = 0
| val y = 5
| }
*<console>:12: warning: Reference to uninitialized value y*
val x = y // compiles OK, x = 0
^
Post by martin odersky
I think that's a suggestion worth considering! In general it is
extremely hard to detect uninitialized fields statically. But a scheme of
disallowing direct forward references is easy to do and catches the most
obvious bugs.
Cheers
- Martin
On Sat, Sep 10, 2016 at 1:42 AM, Sofoklis Papasofokli <
Post by Sofoklis Papasofokli
Hi,
Strange that nobody commented on this one for so long.
I know its an old thread but i keep getting issues from this, I also
believe there should be a compiler error in this situation, its totally
unexpected behavior.
Best Regards,
Sofoklis
Post by Eugen Labun
Hi all,
eventually (or even surely) this is an old question but I haven't
found an explanation for this
simple situation (nor in Language Specification, nor in Scala-Book).
https://github.com/paulp/scala-faq/wiki/Initialization-Order)
Constructions like
def m {
val x = y // compile error "forward reference extends over
definition of value x"
val y = 5
}
cause a compile error if used in methods,
class/object T {
val x = y // compiles OK, x = 0
val y = 5
}
The 'x' in the code above gets initialized to 0 (!), not to 5.
Both -- acceptance by the compiler and initialization to 0 -- are
counterintuitive to me.
Would a compile error for the second case ("illegal forward
reference") not be a more preferable?
I'm aware of '-Xcheckinit' compiler option. But this introduces only
*runtime* check and doesn't
prevent the code to compile.
There was a ticket https://lampsvn.epfl.ch/trac/scala/ticket/399, but
it's closed. I cannot
understand the reason of closing (it cites one more example of such
counterintuitive behavior but
doesn't explain why this behavior can't be changed).
class C {
final int a = 3;
{
System.out.println("a: " + a); // OK
System.out.println("y: " + y); // Error: illegal forward reference
}
final int x = y; // Error: illegal forward reference
final int y = 5;
public static void main(String[] args) {
// final int x = y; // Error: cannot find symbol variable y
final int y = 5;
}
}
I understand that Scala vals do not map 1:1 to Java final variables,
and that generating bytecode
from Scala code is much more complicated (having in mind such things
as unified access principle and
therefore introducing methods for vals/vars, mapping of Scala's
primary constructor to constructors
and initializers in Java, inheritance and overriding val->def->var, ...)
But, despite how complicated can be the generated code, hopefully,
might it be possible to detect
such forward references in Scala parser and generate an error?
--
Regards,
Eugen
--
You received this message because you are subscribed to the Google
Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send
For more options, visit https://groups.google.com/d/optout.
--
Martin Odersky
EPFL and Lightbend
--
You received this message because you are subscribed to the Google
Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups
"scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
Cheers,
√
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Loading...