what happens in scala when loading objects that extends App?
lazy-evaluation, scala
Solution
App extends DelayedInit trait. So all statements and all value definitions are moved to `delayedInit` method. Lazy val works because it compiles to method.
For example if you decompile this class:
class TestApp extends App{
val test = "I am null"
lazy val testLazy ="I am a string"
}
You will get class with 'lazy method':
public String testLazy()
{
if((bitmap$0 & 1) == 0)
synchronized(this)
{
if((bitmap$0 & 1) == 0)
{
testLazy = "I am a string";
bitmap$0 = bitmap$0 | 1;
}
BoxedUnit _tmp = BoxedUnit.UNIT;
}
return testLazy;
}
and delayedInit method in inner class `delayedInit.body`:
public final class delayedInit.body extends AbstractFunction0
implements ScalaObject
{
public final Object apply()
{
$outer.test_$eq("I am null");
return BoxedUnit.UNIT;
}
private final TestApp $outer;
....
So value "I am null" will be assigned to `test` field only when delayedInit is called.
Problem
I've encountered a somewhat bizzar behavior in objects that extends `App`. take a look at the following REPL commands: ``` scala> object A extends App {val x = "I am null"} defined module A scala> object B {val x = "I am a string"} defined module B scala> A.x res0: java.lang.String = null scala> B.x res1: java.lang.String = I am a string ``` well, this is a bit weird... but it gets weirder. i then thought the vals in an `object` go into some lazy evaluation... so i tried a real `lazy val`: ``` scala> object C extends App {lazy val x = "What am I?"} defined module C scala> C.x res2: java.lang.String = What am I? ``` so what's happening here? why is a regular val gets a null value? why does this behavior changes when i use `lazy val`? and what is so special with the `App` trait, that makes the regular vals to be unevaluated?