views:

90

answers:

1

I've been experiencing confusion over packaging classes in Scala and importing packages. Let me start with a pair of simple source files:

file: a/A.scala

package a

// Which of these imports should be used? They both seem to work.
//import a.b._
import b._

class A {
   val fieldB = new B
}

file: a/b/B.scala

package a.b

class B

usage

Compiling with scalac works without complaint with either of the imports above in A.scala

Trying to load these files in the REPL works differently:

$ scala
Welcome to Scala version 2.8.0.r0-b20100714201327 (Java HotSpot(TM) Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :l a/b/B.scala
Loading a/b/B.scala...
<console>:1: error: illegal start of definition
       package a.b
       ^
defined class B

scala> :l a/A.scala
Loading a/A.scala...
<console>:1: error: illegal start of definition
       package a
       ^
<console>:5: error: not found: value b
       import b._
              ^
defined class A

scala>

So, I have a some questions:

  • What is the correct way to do that import in A.scala above?

  • The compiler seems to be able to figure out if an import is relative to the package we are in or if it is absolute, without the _root_. Is that what I'm seeing?

  • Am I doing this correctly in the REPL? Why does it seem so unhappy with seeing package statements, and why does the import b._ generate an error?

Thank you

PS I know the directory structure doesn't have to match the packaging. Doing so voluntarily is helping me to be less confused for now.

+1  A: 

First off you cannot define packages in the REPL. The reason for this is that your REPL-statements are actually wrapped into objects. That's why your :load command fails. You would need to compile your source files and add it to the classpath if you want to use packages.

When trying to resolve a symbol to be imported the compiler tries to find it in your actual scope, i.e. when you write

import a._
import b._

this will import everything from package a and everything from package a.b. If you are inside package a then b is in your scope already and the second import is sufficient. The compiler also initially imports scala._ so you can also use relative imports like import xml._ to import scala.xml._.

In addition there is a feature called nested packages which lets you write your B.scala like

package a
package b
class B { /* .... */ }

which results in everything from package a being imported in this file.

If the compiler cannot resolve an import to a relative symbol it will look in the default package (_root_).

Moritz
That above with two package statements isn't equivilent to `package a.b`?
dino
@dino Mostly it is - with the difference that all of ´a´ gets imported. See also <http://stackoverflow.com/questions/2830248/what-are-nested-unnested-packages-in-scala-2-8> and the links included.
Moritz