Question

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.

Was it helpful?

Solution

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_).

OTHER TIPS

To load your class from the console...

scala> :paste -raw io/hacking/yourpackage/YourClass.scala

If your class has a main you can then invoke it with:

scala> io.hacking.yourpackage/YourClass.main(Array())

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top