本文介绍了根据 Scala 语言规范,包是 AnyRef 值并具有类型.这有什么意义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读 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.您不能将它们分配给 types:

scala>类型 t = java.type<console>:7: 错误:类型不匹配;发现:java.type需要:AnyRef请注意,java 扩展 Any,而不是 AnyRef.这样的类型可以参与值类,但实例不能出现在单例类型或引用比较中.

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

scala>输入 q = Int定义类型别名 q

我怀疑还有其他事情发生

2) 我怀疑这在规范中的唯一原因是支持 package objects.如果我们写

包对象 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 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)?

这篇关于根据 Scala 语言规范,包是 AnyRef 值并具有类型.这有什么意义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 00:01