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.scalaabove? -
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.
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
this will import everything from
package aand everything frompackage a.b. If you are insidepackage athenbis in your scope already and the second import is sufficient.The compiler also initially imports
scala._so you can also use relative imports likeimport xml._to importscala.xml._.In addition there is a feature called nested packages which lets you write your
B.scalalikewhich results in everything from
package abeing imported in this file.If the compiler cannot resolve an import to a relative symbol it will look in the default package (
_root_).