Question

This sounds embarrassing. My purpose is to understand how Scala treats package statements, written in the Java style. To this end, I wrote up a little example class (that I named DinnerTimeP.scala as below:

package dinnertime
 class Dinner { 
  val veggie = "broccoli"
   def announceDinner(veggie: String) {
   println("Dinner happens to be tasteless " + veggie + " soup")
  }
 }

I have a folder called scaladev, under which I have created the package folder, dinnertime. Under this package lives DinnerTimeP.scala. On the DOS command I then navigate to dinnertime and compile the file DinnerTimeP (the name sounds silly) with scalac as below.

C:\scala-2.9.1.final\scala-2.9.1.final\scaladev\dinnertime>set CLASSPATH=.;C:\scala-  2.9.1.final\scala-2.9.1.final\scaladev

C:\scala-2.9.1.final\scala-2.9.1.final\scaladev\dinnertime>scalac DinnerTimeP.scala

I was hoping to find Dinner.class generated right under the dinnertime folder and sitting next to the source file DinnerTimeP.scala. To confirm my understanding, I created a HelloWorld.java program under the same folder:

package dinnertime;

public class HelloWorld {
  public static void main(String[] args) {
  System.out.println("Hello World");
}

}

I compiled HelloWorld.java on the command line as follows: C:\scala-2.9.1.final\scala-2.9.1.final\scaladev\dinnertime>javac HelloWorld.java

The HelloWorld.class file was generated right next to its source file. This was the exact situation I wanted to see with the Scala source file and its compiled file. Instead I see a new package folder generated by Scala inside the package folder dinnertime.

This might be naive. I am probably betraying a fundamental understanding of Scala and packages, but I was perplexed by this behaviour. This is the problem I can't explain to myself: Why is the nested package created for the newly generated class file. This is the problem to which I which I had hoped to solve, based on my own sincere efforts Because my experience with Scala at the present time is limited, I have resorted to asking the Scala gurus on stackoverflow to help me understand what is going on and why? Is there a reason for this nested package to be created by Scala and not by Java?

Was it helpful?

Solution

Tomasz explained everything you need to get it working, so let me explain the why.

Scala does not mandate that source files be in a directory hierarchy that reflects the packages. That is, Dinner.scala could be anywhere: it simply doesn't matter.

And, to be really clear, even if you have a complex package hierarchy, deep and with multiple subpackages at each level, you can put all source files in a single directory. The directory where Scala files are put in is not relevant.

Sorry for giving it so much emphasis, but coming from Java it might be difficult to grasp this.

Ok, now, how to explain dinnertime/Dinner.class? Well, JVM demands that class file be put in a directory hierarchy that corresponds to the package names, so even if Scala source files can be put in arbitrary directories, scalac must produce an output whose directory structure reflects the package names.

So, to review everything, Scala doesn't care what directory you were in, so it ignored the fact that you were in a directory called dinnertime. However, since the source code indicated that the class was in a package named dinnertime, it created such directory and put the class file in it. It assumed the base for that was the current directory, which can be changed with the -d parameter, as per Tomasz answer.

OTHER TIPS

First of all try compiling from the root directory, so that dinnertime is a subdirectory:

$ javac dinnertime/HelloWorld.java

and:

$ scalac dinnertime/Dinner.scala

They both produce the same output, i.e. in both cases .class file is placed under dinnertime subdirectory.

The difference arises when you run a compiler inside a package. Turns out javac is clever enough to put target binary files relative to root directory, not current direcotyr. This is not the case with scalac which always uses current directory as base. You can easily fix this by using -d parameter:

$ cd dinnertime
$ scalac -d .. Dinner.scala
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top