Adding default package imports
Asked Answered
S

4

7

In Java, Scala, or generally any JVM language, there is a set of packages that is imported by default. Java, for instance, automatically imports java.lang, you don't need to do it in your Java code file.

Now I don't know which component takes care of this exactly (the compiler? the JVM?), but is there any way to have additional packages or even classes imported by default?

Say you have a package defining a set of utility functions you use throughout your project (an example could be scala.math in Scala), it would be great if you were able to skip the import for it in every math related class.

Systemize answered 17/2, 2011 at 7:44 Comment(3)
"it would be great if you were able to skip the import". Why? Modern IDEs have auto-complete and functions to add imports as needed. Besides, imports are intended mostly to document the code for other programmers. If the imports are missing, how is the programmer supposed to know that it uses 3rd arty classes?Swan
Your latter point, in my opinion, should be a decision made by the project author. You could write books about that issue, so I'd like to put it aside here. About your first point, true, any modern Java IDE can auto-resolve a class name and add an import. So this might be an issue related to Scala only. In Scala (2.8), you can have "package objects" that can define fields and methods on a package scope. You make those definitions visible as if they were defined in the class you're working in by importing the package (using the wildcard). No IDE supports that at this moment from what I know.Systemize
@AndrewThompson, Boilerplate hindrance to my eyes = inefficiency.Gregg
A
12

Scala, as of 2.8, has package objects, the contents of which are automatically imported into every file of the package. Create a file called package.scala in the top level directory of your package (e.g., x/y/z/mypackage), and put into it

package x.y.z

package object mypackage {
  ...
}

Then any definition within the package object is automatically imported (i.e., no import statement is needed) into any file in package x.y.z.mypackage

You can take a look at the Scala sources -- do a find dir -name package.scala -- there are a bunch of them, the topmost defining the implicit imports for the scala package itself, which are automatically imported into every scala source file.

Acrolith answered 17/2, 2011 at 11:8 Comment(8)
Good point. For any code within a given package, this is a good solution. +1Realize
@Realize Saying +1 is nice, but actually uprating the answer would be even nicer. :-)Acrolith
This works as long as you are working in one and the same package, I'm already making use of this. However, usually you work with package trees. Unfortunately, package objects can't be inherited and definitions inside a package object do not affect any sub packages. That would allow me to define a package object for the root package and everything would be fine. I hope this will be possible in the future.Systemize
@Systemize You can, however, put imports into your package objects, giving you a form of manual inheritance.Acrolith
Aha! That didn't get quite clear in your posting (IMO), would be good if you added it. In that case this is a great emulation indeed! Not quite the perfection I'm looking for yet ;) but the best that's within the possibilities.Systemize
@Systemize Unfortunately it doesn't seem to work -- the import in the package object is apparently locally scoped, sigh.Acrolith
@Jim Balter Got to unaccept then. So in all it looks like there is no cross-package way so far. I might file package object inheritance as an issue in the Scala tracker if it doesn't already exist.Systemize
@Realize Ok, thanks -- perhaps SO has some sort of delay, as I do not believe it was there when I posted that comment.Acrolith
R
11

Jim Balter mentions in his answer (go upvote it) the Scala 2.8 package object.

Any kind of definition that you can put inside a class, you can also put at the top level of a package. If you have some helper method you'd like to be in scope for an entire package, go ahead and put it right at the top level of the package.

To do so, put the definitions in a package object. Each package is allowed to have one package object

Scala actually has its own scala package object.
See "Where to put package objects".

So package object can solve the problem of explicit import for a given package, but not for any package.
Its current limitations include:

  • First, you cannot define or inherit overloaded methods in package objects.
  • Second, you cannot define or inherit a member in a package object which is also the name of a top-level class or object in same package.

We expect that some future Scala release will drop these restrictions.


Original answer:

On the Scala side, a question like "should Scala import scala.collection.JavaConversions._ by default?" shows that you cannot just add default imports as a Scala user.
It has to be supported by the language.

By the way, the conclusion was:

From a Scala expert perspective: Let's keep things simple and limit the implicits that are imported by default to the absolute minimum.
Heiko Seeberger


Raphael does comment though:

I guess you could write your own compiler plugin to add some packages?

And sure enough, this Scala article describe how to extend the Scala compiler.
But the main additions supported are:

  • You can add a phase to the compiler, thus adding extra checks or extra tree rewrites that apply after type checking has finished.
  • You can tell the compiler type-checking information about an annotation that is intended to be applied to types.

So even with a tree rewrite (including additional imports), I am not sure said rewrite would be done in time for the types and functions (referenced by the implicit imports you are asking for) can be correctly analyzed.
But maybe the Scala Compiler Corner has more ideas on that.

Realize answered 17/2, 2011 at 7:54 Comment(2)
I guess you could write your own compiler plugin to add some packages?Collyer
Things have changed in Scala 2.8; see my answer.Acrolith
A
4

The default import of all classes from java.lang is specified in the Java language Specification (7.5.5)

All other classes have to be import with the import statement.

Anastigmat answered 17/2, 2011 at 8:14 Comment(0)
E
1

In Java there is not a way to do that.

Etherify answered 17/2, 2011 at 7:47 Comment(3)
I understand that this is comprehensibility vs coding efficiency, and that the Java philosophy tries to maintain a good comprehensibility of code (which, IMO, it fails at in several ways, but that's not the matter at hand), but for my project I chose coding efficiency (which is also why I prefer Scala over Java), and a feature like this would make life a lot easier for me. You're supposed to stuff functions in appropriately named classes, and the reward for doing so is having to import tons of packages and classes everywhere they are needed - not too nice IMO.Systemize
@Systemize Please see my answer; Scala has the feature you're looking for.Acrolith
A large number of imports indicates your class is probably doing too much and should be refactored. Hiding the imports somehow would hide that issue.Etherify

© 2022 - 2024 — McMap. All rights reserved.