问题描述
我正在阅读 Scala 语言规范,但遇到了一些令人困惑的事情,即包是值而它们确实有类型的含义.
以下是我从 Scala 语言规范中得出的(可能是错误的?)这个奇怪的事实:
背景:
在定义:
SimpleType ::= SimpleType ‘#’ id
类型投影 T#x 引用类型 T 的名为 x 的类型成员.
最后,单例类型 定义说:
SimpleType ::= 路径‘.’类型
单例类型的形式为 p.type,其中 p 是指向预期符合的值的路径Scala.AnyRef.类型表示由 null 组成的值集和 p 表示的值.
推理链:
所以,我们知道:
1) scala.Int
中的 scala
是一个包.
2) scala.Int
只是 scala.type#Int
的语法糖(如 类型指示符定义,如上图所示)
3) scala.type#Int
是类型投影,其中 scala.type
必须是根据 类型投影定义 指出:
类型投影 T#x 引用类型 T 的名为 x 的类型成员.
4) 所以 scala.type
是一种类型!也就是说,它是一种单例类型,根据 单例类型的定义,它说:
单例类型的形式为 p.type,其中 p 是指向的路径预期符合 scala.AnyRef 的值.
5) scala
对应于 p
是一个符合 AnyRef
6) 在 Scala 语言规范中 这里是这样写的:
Scala 中的每个值都有一个类型...
7) 所以包 scala
有一个类型.
问题:
1) 这个推理正确吗?包 scala
真的是一个符合 AnyRef 的值吗?如果此推理不正确,请解释原因.
假设上面的推理是正确的,并且包scala
确实是一个值:
2) 包 scala
在什么意义上是一个值?这还有什么道理?在什么上下文中,我们可以将 scala
视为一个值,就像我们将 5:Int
视为具有类型的值 5
一样Int
?
3) 如果包 scala
是一个符合 AnyRef 的值,那么我应该能够将该值放入一个变量中,我可以这样做,如果不是,那为什么不呢?
4) scala
包的值是如何在幕后内部(由编译器)表示的?它是一个对象吗?这个值在运行时以 JVM 对象的形式存在吗?如果是,我怎样才能得到它?如何在其上调用 toString
方法?
基于实验而非规范:
1) 包有类型,但它们符合Any
,而不是AnyRef
.您不能将它们分配给 type
s:
scala>类型 t = java.type<console>:7: 错误:类型不匹配;发现:java.type需要:AnyRef请注意,java 扩展 Any,而不是 AnyRef.这样的类型可以参与值类,但实例不能出现在单例类型或引用比较中.
有趣的是,这并不是对 Any
类型的一般限制:
scala>输入 q = Int定义类型别名 q
我怀疑还有其他事情发生
2) 我怀疑这在规范中的唯一原因是支持 package object
s.如果我们写
包对象 foo {值 x = 5val y = 这个}
那么说 foo
不是值会很奇怪(特别奇怪的是说 y
不是值).如果一个普通的包只要我们为它定义了一个包对象
就神奇地产生了一个值,那也很奇怪.
3) 我看不到任何方法,因为我看不到任何访问该值的方法.错误甚至说包不是值:
val f = footest.scala:10: 包 foo 不是值
可能值 foo
在某种意义上存在",但是没有办法在源代码中命名它(包对象本身除外)?
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 :
Furthermore, by considering the type projection definition:
Lastly, the singleton type definition says :
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:
4) So scala.type
is a type ! Namely, it is a singleton type, according to the definition of singleton types, which says :
5) scala
corresponds to p
which is a value conforming to AnyRef
6) In the Scala Language Specification here it is written that:
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 ?
Based on experimentation rather than the specification:
1) packages have types but they conform to Any
, not AnyRef
. You can't assign them to 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.
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 object
s. 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)?
这篇关于根据 Scala 语言规范,包是 AnyRef 值并具有类型.这有什么意义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!