2

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.

dino
  • 1,123
  • 9
  • 13

2 Answers2

6

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
  • 14,144
  • 2
  • 56
  • 55
  • That above with two package statements isn't equivilent to `package a.b`? – dino Jul 26 '10 at 15:00
  • @dino Mostly it is - with the difference that all of ´a´ gets imported. See also and the links included. – Moritz Jul 26 '10 at 15:08
  • As of now, the statement `you cannot defines packages in the REPL` is not true - you can use the `:paste raw` command to get that done - paste the entire code of a package definition, and the press `Ctrl + D` to run it. – Lucas Lima Nov 28 '19 at 15:41
0

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())

Langley
  • 499
  • 6
  • 12