根据Scala语言规范,包是AnyRef值并且具有类型。这有什么意义?

时间:2014-11-05 09:52:10

标签: scala specifications language-specifications

我正在阅读Scala语言规范,我遇到了一些令人困惑的事情,即暗示包是值,而且它们有类型

以下是我从Scala语言规范中得出的结论(可能不正确?)这个奇怪的事实:

背景

type designators部分,写着:

  

SimpleType :: = StableId

     

类型指示符指的是命名值   类型。它可以是简单的或合格的。所有这些类型的指示符都是   类型预测的缩写。

     

具体来说,非限定类型名称t其中t绑定在某些中   class,object或 package C 被视为C.this.type #t 的简写。   如果t未绑定在类,对象或包中,则t被视为a   ε.type#t的简写。

     

合格的类型指示符的形式为p.t,其中p是路径和t   是一个类型名称。这种类型的指示符等同于类型   投影p.type #t。

     

下面列出了一些类型标识符及其扩展名。我们假设一个局部类型参数t,一个值可维护,带有一个类型成员Node和标准类scala.Int,

enter image description here

此外,通过考虑type projection定义:

  

SimpleType :: = SimpleType'#'id

     

类型投影 T#x引用类型为T的类型成员T

最后,singleton type定义说:

  

SimpleType :: = Path'。'type

     

单例类型的形式为p.type,   其中p是指向期望符合的值的路径   scala.AnyRef。该类型表示由null组成的值集   和p。

表示的值

推理链:

所以,我们知道:

1)scala中的scala.Int是一个包。

2)scala.Int只是scala.type#Int的语法糖(如type designator definition中所述,如上图所示)

3)scala.type#Int是一种类型投影,其中scala.type必须是符合the type projection definition的类型:

  

类型投影T#x引用类型为T的类型成员。

4)所以 scala.type是一种类型!也就是说,它是单身类型,根据definition of singleton types,它说:

  

单例类型的形式为p.type,其中p是指向的路径   一个符合scala.AnyRef的值。

5)scala对应p,这是符合AnyRef的

6)在Scala语言规范here中写道:

  

Scala中的每个值都有一个类型......

7)所以包scala有一个类型。

问题

1)这个推理是否正确?包scala真的是一个符合AnyRef的值吗?如果这种推理不正确,请解释原因。

假设上述推理是正确的并且包scala确实是一个值:

2)包scala在什么意义上是一个值?这怎么有意义呢?在什么情况下,我们可以将scala视为一个值,就像我们认为5:Int5类型Int的价值一样?

3)如果包scala是一个符合AnyRef的值,那么我应该能够将该值放入变量中,我可以这样做,如果没有,那么为什么不呢?

4)包scala的值是如何在幕后内部(由编译器)表示的?它是一个对象吗?此值是否以JVM对象的形式存在于运行时?如果是的话,我怎么能抓住它呢?如何在其上调用toString方法?

1 个答案:

答案 0 :(得分:5)

基于实验而不是规范:

1)包有类型,但它们符合Any,而不是AnyRef。您无法将其分配给type s:

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.

有趣的是,这不是对Any类型的一般限制:

scala> type q = Int
defined type alias q

我怀疑其他事情正在发生

2)我怀疑这个规范的唯一原因是支持package object。如果我们写

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

那么说foo不是一个值(特别奇怪的是y不是一个值)会很奇怪。如果一个普通的软件包在我们为它定义package object后立即疯狂地发布了一个值,那也会很奇怪。

3)我无法看到任何方法,因为我无法看到任何方式来访问该值。该错误甚至表示包不是值:

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

foo&#34;可能存在&#34;从某种意义上说,但是没有办法在源代码中命名它(在包对象本身中除外)?