0

Given:

src/main/scala/net/Foo.scala

package net

object Foo {
  ???
  val x = 100
}

src/main/scala/net/Bar.scala

package net

object Bar {
 import Foo._
 def speak = "bar!"
}

I opened up the REPL to call Bar#speak:

scala> import net.Bar
import net.Bar

scala> Bar.speak
res0: String = bar!

I had expected Bar to have initialized Foo, resulting in an exception getting thrown with ???.

Why wasn't this exception thrown?

1
  • Imports never have effects. Commented Sep 1, 2015 at 3:51

2 Answers 2

2

This is what you had:

scala> object Foo {
     |   ???
     |   val x = 100
     | }
defined object Foo

scala> object Bar {
     |  import Foo._
     |  def speak = "bar!"
     | }
defined object Bar

scala> Bar.speak
res0: String = bar!

scala> Bar.speak
res1: String = bar!

import Foo._ means that for compilation purposes to resolve names members of Foo will be available in the scope. It does not mean that Foo has to be initialized at this point - Scala is being lazy here. Now contrast with this example:

scala> object Foo {
     |   ???
     |   val x = 100
     | }
defined object Foo

scala> object Bar {
     |   val blowUp = Foo.x
     |   def speak = "bar!"
     | }
defined object Bar

scala> Bar.speak
scala.NotImplementedError: an implementation is missing
  at scala.Predef$.$qmark$qmark$qmark(Predef.scala:225)
  ... 37 elided

It forces Foo to get initialized because it uses Foo.x in its own initialization which in turn is triggered by calling speak. Simplified example:

scala> object Foo {
     |   ???
     |   val x = 100
     | }
defined object Foo

Didn't blow up yet. Foo is not initialized.

scala> Foo.x
scala.NotImplementedError: an implementation is missing
  at scala.Predef$.$qmark$qmark$qmark(Predef.scala:225)
  ... 35 elided

Now we forced Foo to get initialized.

In short there are 2 important things here: 1) lazy initialization upon reference/call and 2) import does not cause initialization.

Sign up to request clarification or add additional context in comments.

Comments

2

Because Bar doesn't actually refer to Foo anywhere. If Bar.speak used Foo or Foo.x in some way, you would get the expected exception. import puts Foo's members into scope, but doesn't access them.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.