3

I am reading through the Scala Language Specification and I have encountered something confusing, namely, the implication that packages are values and they do have types.

Here is how I concluded (maybe incorrectly?) this strange fact from the Scala Language Specification:

Background:

In the type designators section, it is written :

SimpleType ::= StableId

A type designator refers to a named value type. It can be simple or qualified. All such type designators are shorthands for type projections.

Specifically, the unqualified type name t where t is bound in some class, object, or package C is taken as a shorthand for C.this.type#t. If t is not bound in a class, object, or package, then t is taken as a shorthand for ε.type#t.

A qualified type designator has the form p.t where p is a path and t is a type name. Such a type designator is equivalent to the type projection p.type#t.

Some type designators and their expansions are listed below. We assume a local type parameter t, a value maintable with a type member Node and the standard class scala.Int,

enter image description here

Furthermore, by considering the type projection definition:

SimpleType ::= SimpleType ‘#’ id

A type projection T#x references the type member named x of type T.

Lastly, the singleton type definition says :

SimpleType ::= Path ‘.’ type

A singleton type is of the form p.type, where p is a path pointing to a value expected to conform to scala.AnyRef. The type denotes the set of values consisting of null and the value denoted by p.

Chain of reasoning:

So, we know that :

1) scala in scala.Int is a package.

2) scala.Int is just syntactic sugar for scala.type#Int (as explained in the type designator definition and shown in the image above)

3) scala.type#Int is a type projection, where scala.type must be a type according to the type projection definition which states:

A type projection T#x references the type member named x of type T.

4) So scala.type is a type ! Namely, it is a singleton type, according to the definition of singleton types, which says :

A singleton type is of the form p.type, where p is a path pointing to a value expected to conform to scala.AnyRef.

5) scala corresponds to p which is a value conforming to AnyRef

6) In the Scala Language Specification here it is written that:

Every value in Scala has a type...

7) So the package scala has a type.

Questions:

1) Is this reasoning correct? Is the package scala really a value conforming to AnyRef ? If this reasoning is not correct, please explain why.

Assuming that the above reasoning is correct and the package scala is indeed a value:

2) In what sense is the package scala a value ? How does that even make sense ? In what context can we think of scala as a value in the same way as we think of 5:Int being the value 5 with the type Int?

3) If the package scala is a value that conforms to AnyRef, then I should be able to put that value into a variable, can I do that, if not, then why not ?

4) How is the value of the package scala represented internally (by the compiler) behind the scenes ? Is it an object ? Is this value present at runtime in the form of a JVM object ? If yes, how can I get a hold of it ? How can I call the toString method on it ?

jhegedus
  • 20,244
  • 16
  • 99
  • 167

1 Answers1

5

Based on experimentation rather than the specification:

1) packages have types but they conform to Any, not AnyRef. You can't assign them to types:

scala> type t = java.type
<console>:7: error: type mismatch;
 found   : java.type
 required: AnyRef
Note that java extends Any, not AnyRef.
Such types can participate in value classes, but instances
cannot appear in singleton types or in reference comparisons.

Interestingly this is not a general restriction on Any types:

scala> type q = Int
defined type alias q

I suspect something else is going on

2) I suspect the only reason this is in the spec is to support package objects. If we write

package object foo {
  val x = 5
  val y = this
}

then it would be weird to say that foo isn't a value (and especially weird to say that y isn't a value). And if an ordinary package magically sprouted a value as soon as we defined a package object for it, that would also be weird.

3) I can't see any way to do it, because I can't see any way to access the value. The error even says that the package is not a value:

val f = foo
test.scala:10: package foo is not a value

It may be that the value foo "exists" in some sense, but there's no way to name it in source (except within the package object itself)?

lmm
  • 17,386
  • 3
  • 26
  • 37
  • Thank you for the valuable experimental contribution ! – jhegedus Nov 05 '14 at 11:16
  • 2
    When you say `Int.type`, you refer to the companion object of class Int. – Eugene Burmako Nov 05 '14 at 12:53
  • 2
    4) scalac doesn't have a repr of a value of the package `scala`, but it does have a repr of its type. Internally, we use the same data structure to represent type signatures of classes, traits, objects and packages. It's called ClassInfoType and contains all the declarations of the corresponding thing as well as references to base classes/traits (I'm simplifying a bit here, but those details don't matter). This is, however, just a convenience that enables uniform treatment of classes, traits, etc internally in scalac. Neither at compile-time, nor at runtime there exist values for packages. – Eugene Burmako Nov 05 '14 at 12:59
  • 1
    2) I think that part of the spec was written before package objects were introduced into the language. – Eugene Burmako Nov 05 '14 at 13:01
  • So is this a mistake in the Scala Lang. Spec. ? Or is there a mistake somewhere in my reasoning ? – jhegedus Nov 05 '14 at 14:08
  • So the type of the companion object of `Int` is `Int.type` ? – jhegedus Nov 05 '14 at 14:11
  • 1
    Looks like a mistake, yes, but I'm not 100% sure. Yes, it's Int.type. – Eugene Burmako Nov 06 '14 at 09:57