forward reference errors

47 views
Skip to first unread message

HjP

unread,
Jun 17, 2012, 9:12:50 PM6/17/12
to scala-user
Why does this program compile without error

object Main {
def main(args: Array[String]) {
class NotUsed {val x = f}
def f = true
}
}

whereas I get a forward reference error if I change 'def f = true' to
'val f = true'.

Naftoli Gugenheim

unread,
Jun 17, 2012, 10:38:18 PM6/17/12
to HjP, scala-user
Because val is not just a method definition, it's also a field initialization statement. Until that line is executed, f will contain null, so therefore it's illegal to reference it before it's initialized.
But a def doesn't need any code to execute to be valid --- it's just there --- so you can call it at any time.

Daniel Sobral

unread,
Jun 18, 2012, 9:16:28 AM6/18/12
to Naftoli Gugenheim, HjP, scala-user
Actually, if "val f" *was* a field initialization statement, it would
be valid. For instance, it would be valid on the body of "Main",
instead of the body of method "main".

It's a local val, and forward references to local vals are not allowed.

Technically, since they are allocated on the stack, instead of being
relative pointers into the memory allocated to object "this" on the
heap, they may not exist until the time they are first initialized. A
field, on the other hand, has its memory allocated from the outset,
and even zeroed by JVM.
--
Daniel C. Sobral

I travel to the future all the time.

HjP

unread,
Jun 18, 2012, 9:44:54 AM6/18/12
to scala-user
And why does this program yield a forward reference error?

object Main {
def main(args: Array[String]) {
class NotUsed {val x = f}
val dummy = false
def f = true
}
}

Dominik

unread,
Jun 19, 2012, 5:55:47 AM6/19/12
to scala...@googlegroups.com
I would say that the compiler does not make a full data flow analysis but reports an error if a possible conflict could exist.
In your case it could be that f depends directly or indirectly on dummy and that dummy is accessed before it is defined, as in

        def main(args: Array[String]) {
                class NotUsed {val x = f}
                println(new NotUsed().x)
                val dummy = 3
                def f = dummy
        }

you can avoid this by
a) either declaring the local vals at the beginning of the block (or at least before any use of local members) or
b) by declaring them lazy.
Dominik
Reply all
Reply to author
Forward
0 new messages