Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Motivation behind Scala package objects [closed]

Tags:

scala

What are the advantages of the object package syntax over simply letting you add functions and variables to a package ?

example:

package object something {
   def hello = 0
}

package something {

}

Why not simply:

package something {
   def hello = 0
  // other classes and such
}
like image 436
Derlin Avatar asked Mar 06 '26 12:03

Derlin


1 Answers

You could even go one step further: why have packages at all, when we have objects?

Scala is intended to be useful as a "hosted language", i.e. a language that can play nicely being hosted on top of another language's platform. The original implementations of Scala were on the Java platform and the ISO Common Language Infrastructure platform (or rather its primary implementations, .NET and Mono). Today, we also have an implementation on the ECMAScript platform (Scala.js), and the Java platform implementation can also be used on Android, for example. You can imagine other interesting platforms as well, that you would like to run Scala on, e.g. the Windows UWP platform, the Swift/Objective-C/Core Foundation/macOS/iOS/tvOS/watchOS platform, the Gnome/GObject platform, the Qt/C++ platform, etc.

Scala does not just intend to run on those platforms, it intends to fulfill two, often conflicting, goals:

  • high performance
  • tight integration with a "native" feel

So, in Scala, implementation concerns are part of language design. (Rich Hickey, the designer of Clojure, once said in a talk "the JVM is not an implementation detail", the same applies to Scala.) A good example are proper tail calls: in order to support proper tail calls, Scala would have to manage its own stack instead of using the host platform's native call stack on platforms like the JVM, which however means that you can no longer easily call Scala code from other code on the platform and vice versa. So, while proper tail calls would be nice to have, Scala settles for the less powerful proper immediate tail recursion.

Theoretically, Scala needs only objects, traits, methods, types, and paths (. and #). Everything else is basically just there to ease integration with the host platform. This includes, for example, null, classes, and packages.

Ideally, there should be an easy mapping from host platform constructs to Scala constructs and vice versa. So, for example, there is an easy mapping between Scala methods and JVM methods. There is an easy mapping between JVM interfaces and Scala traits with only abstract members. There is no easy mapping between Scala traits and JVM classes, which is why Scala has the (redundant) concept of classes as well. And similarly, there is no easy mapping between Scala objects and JVM packages (or CLI namespaces), which is why Scala has the (redundant) concept of package as well.

However, we would really like packages (which are, after all, somewhat like Scala objects) to have members as well. But JVM packages and CLI namespaces can't have members other than interfaces and classes, and since we only introduced them in Scala for compatibility with the host platform it simply doesn't make sense to make them incompatible with the host platform by adding members to them.

So, we introduce yet another separate concept, the package object, which holds the members we would like to add to packages but can't, because of host platform interoperability.

tl;dr:

  • we have packages because of interop (even though we already have objects, which can do all the same things as packages)
  • we would like packages to have members
  • packages can't have members, because interop
  • so, we have package objects as companions to packages
like image 188
Jörg W Mittag Avatar answered Mar 08 '26 00:03

Jörg W Mittag