Motivating Scala Package Objects

What are the benefits of the object package syntax by simply allowing you to add functions and variables to the package?

Example:

package object something {
   def hello = 0
}

package something {

}

      

Why not just:

package something {
   def hello = 0
  // other classes and such
}

      

+3


source to share


1 answer


You can even go even further: why are there packages at all when we have object

s?

Scala is intended to be used as a "hosted language", that is, a language that can reproduce well on another language platform. The original implementations of Scala were in the Java platform and the Common Language Infrastructure platform (or rather, its main 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 that you would like to run Scala on, for example. Windows UWP platform, Swift / Objective-C / Core Foundation / macOS / iOS / tvOS / watchOS platform, Gnome / GObject platform, Qt / C ++ platform, etc.

Scala not only intends to run on these platforms, it intends to accomplish two often conflicting goals:

  • high performance
  • tight integration with the "native" feeling.

So in Scala, implementation problems are part of the design of the language. (Rich Hickey, a Clojure developer, once said in a conversation "The JVM is not an implementation detail," the same applies to Scala.) Correct tail calls are a good example: To support correct tail calls, Scala would have to manage its own stack. rather than using the native call stack on the host platform on platforms such as the JVM, which however means you can no longer easily call Scala code from other code on the platform and vice versa. So while correct tail calls would be fine, Scala settles for less strong proper direct tail recursion.

Theoretically only requires Scala object

s, trait

s, techniques, type

s, and the path ( .

and #

). Anything else basically just makes it easier to integrate with the host platform. This includes, for example null

, class

es and package

s.



Ideally, it should be easy to map 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 a simple mapping between JVM interfaces and Scala traits with only abstract elements. There is no easy mapping between Scala traits and JVM classes, so Scala has a (redundant) concept of classes. Likewise, there is no simple mapping between Scala object

and the JVM package

(or CLI namespace

s), so Scala has a (redundant) concept package

.

However, we would really like it package

(which are, after all, somewhat similar to Scala object

s) to have members. But the JVM package

and CLI namespace

cannot have members other than interface

and class

es, and since we only introduced them into Scala for compatibility with the host platform, it just doesn't make sense to make them incompatible with the host platform by adding members to them.

So, we introduce another separate concept package object

that contains elements that we would like to add to package

, but cannot, due to compatibility with the host platform.

TL; DR :

  • we have package

    because of interaction (although we already have object

    s that can do all the same things as package

    s)
  • we would like to package

    have members
  • package

    cannot have members because interop
  • So, we have package object

    as companions for package

    s
+6


source







All Articles