Dropped: Package Objects says package objects will be dropped. But there’s three areas which the replacement (top level definitions) does not suffice:
-
Top-level definitions does not allow statements like
println(1). Or it does, but you need to wrap them inval _ = println(1). This seems like a pretty silly restriction with a pretty silly workaround.- Given we already allow top-level wrapper objects to have non-lazy initialization logic with
vals, we should just allow top level statements. Apart from improving consistency and removing a weird restriction/workaround, this would also make vanilla.scalafiles to be usable for scripts without custom wrapping like Ammonite and Scala-CLI do. Other typed/compiled languages like C# allow top level statements without issue, in scripting languages like Python/Ruby/Javascript this is the default, and of course Ammonite/Scala-CLI demonstrate there’s a broad use case even in Scala (and.ktsin Kotlin or.fsiin Fsharp)
- Given we already allow top-level wrapper objects to have non-lazy initialization logic with
-
Top-level wrapper objects cannot inherit from traits or classes. This is pretty common in my experience, e.g. having
package object foo extends Thinghave the default instance of something andpackage foo; object Bar extends Thingandpackage foo; object Qux extends Thinghave other available instances, all of which implement the same interface and inherit the same implementations.- One limitation of doing this is that you can’t do
val x = foowhenfoois a package object, as it complainspackage foo is not a value, and you have to sayval x = foo.package. This seems like a restriction that should be liftable right, to makeval x = fooautomatically expand toval x = foo.package? That would help smooth out one of the warts of package objects today
- One limitation of doing this is that you can’t do
-
package objects serve as a natural place to put package-level Scaladoc and other documentation, similar tomodule-info.javafiles or python__init__.pyfiles. Without that, there’s nowhere to put “package scaladoc”.readme.mdfiles work fine when browsing the repo but are not slurped up by scaladoc.
All of these seem fixable, but thinking further, what is a package object other than object package; export package.*? I understand having top-level definitions is great, but given that package objects seem to have a pretty trivial desugaring in terms of other existing language features, it seems like the cost of keeping them around indefinitely for backwards compat isn’t too much. And other languages have module-info.java or __init__.py files that serve similar purposes, which indicates to me that the idea of a “primary file for a folder full of files” does have value as a general abstraction