Change SummaryTopWhat Has ChangedWhy the Change?Contents

Why the Change?

The meaning of packages in Scala and Java differs in some respects. Java has four different name resolution mechanisms: one each for methods, fields, classes, and packages. For packages the resolution is that you would always start at the root when resolving a package name. So package names are always absolute, never relative to the current scope. Scala is simpler and more regular. There's only one way to a resolve a simple name, no matter what kind of name the compiler is looking at. When it encounters a simple name x, the compiler will look from the current scope outwards until it finds a declaration of x and that is the declaration that's chosen. This is the standard idea of block-structured scoping. A consequence is that declarations in a nested scope can shadow declarations in some outer scope.

Like all other entities, packages can be nested in Scala. This often leads to more concise code. For instance, assume you have another package org.myproject.web which you want to access inside the package org.myproject.tests. You can do so easily by just writing

import web._ 

There's no need to import the whole path

import org.myprojec.web._ 

As package names grow longer, this style can reduce quite a bit of clutter. So this nesting convention is useful and it is also quite elegant because it needs no specialized rules for packages of the kind Java has.

Unfortunately, it turns out that the nesting convention had an unwelcome side effect in practice. Sometimes people would encounter a nested package with the same name as a root package. For instance, they might have a package somewhere on the classpath. Now, Scala's original nesting convention up to version 2.7 prescribed that inside package org.myproject the name java should resolve to instead of the root package java. This caused confusion and consternation in users who might not even have known that the org domain contained a java package which hides the root java they wanted to access. Worse, the availability of the nested java would depend on how the classpath was defined, what jars were on it etc. Who knows at all times what's on their classpath?

Of course, there was a way around it. Scala has a name for the "root" package that contains all other toplevel packages. It's named _root_. So people could refer to the standard java package as However, to be defensive, you'd have to qualify all references to top level packages with _root_, just to make sure that they would not be accidentally hidden by a like-named nested package.

In summary we were faced with the situation that the shortest and most straightforward way to organize package clauses was fragile because nested packages that ended up accidentally on the classpath could shadow toplevel packages. The more defensive approach that avoided the problem was comparatively verbose and ugly.

Next: Change Summary

Change SummaryTopWhat Has ChangedWhy the Change?Contents