Eugen Labun
2011-03-22 15:14:16 UTC
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
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