【问题标题】:What types are special to the Scala compiler?Scala 编译器有哪些特殊类型?
【发布时间】:2017-02-25 19:50:48
【问题描述】:

Scala 非常重视如何将看似语言的功能实现为库功能。

有语言特殊处理的类型列表吗?

是在规范中还是作为实现细节?

这将包括,例如,优化元组上的匹配。

关于模式匹配、理解、try-catch 块和其他语言结构的特殊约定怎么样?

String 对编译器来说有什么特别之处吗?我看到字符串增强只是一个库隐式转换,Predef 支持字符串连接,但语言是否有特殊情况?

同样,我看到有关<:<classOfasInstanceOf 的问题,不清楚什么是神奇的内在。有没有办法通过编译器选项或通过查看字节码来区分?

我想了解某个功能是否被 Scala.JS 和 Scala-native 等实现统一支持,或者某个功能是否实际上可能被证明是依赖于实现的,具体取决于库实现。

【问题讨论】:

标签: scala


【解决方案1】:

编译器“已知”的类型数量惊人,并且在不同程度上是特殊的。您可以在 scalac 的Definitions.scala 中找到完整列表。

我们大概可以根据它们所具有的特殊程度对它们进行分类。

免责声明:我可能忘记了更多。

类型系统专用

以下类型对 Scala 的类型系统至关重要。它们会影响类型检查本身的执行方式。所有这些类型都在规范中提到(或者至少,它们肯定应该提到)。

  • AnyAnyRefAnyValNullNothing:位于 Scala 类型系统顶部和底部的五种类型。
  • scala.FunctionN,匿名函数(包括 eta 扩展)的(规范)类型。即使在对匿名函数进行 SAM 处理的 2.12 中,FunctionN 在某些情况下仍然很特殊(尤其是在重载决议中)。
  • scala.PartialFunction(影响类型推断的工作方式)
  • Unit
  • 所有带有文字符号的类型:IntLongFloatDoubleCharBooleanStringSymboljava.lang.Class
  • 所有数字基本类型和Chars,用于弱一致性(这两个项目符号一起涵盖所有基本类型)
  • Option 和元组(用于模式匹配和自动元组)
  • java.lang.Throwable
  • scala.Dynamic
  • scala.Singleton
  • 大部分scala.reflect.*,尤其是ClassTagTypeTag
  • scala.annotation.{,ClassFile,Static}Annotation
  • scala.annotation.* 中的几乎所有注解(例如,unchecked
  • scala.language.*
  • scala.math.ScalaNumber(原因不明)

被编译器称为某些语言特性的脱糖

以下类型对于类型系统来说并不重要。它们对类型检查没有影响。但是,Scala 语言确实具有许多可以将这些类型的表达式脱糖的结构。

规范中也会提到这些类型。

  • scala.collection.SeqNilWrappedArray,用于可变参数。
  • TupleN 类型
  • ProductSerializable(用于案例类)
  • MatchError,由模式匹配构造生成
  • scala.xml.*
  • scala.DelayedInit
  • List(编译器对它们进行一些简单的优化,例如将List()重写为Nil

知道该语言的实现

这可能是您最关心的列表,因为您说您有兴趣了解不同后端的不同之处。前面的类别由编译器的早期(前端)阶段处理,因此由 Scala/JVM、Scala.js 和 Scala Native 共享。此类别通常是编译器后端已知的,因此可能具有不同的处理方式。请注意,Scala.js 和 Scala Native 都尝试在合理程度上模仿 Scala/JVM 的语义。

语言规范本身可能没有提到这些类型,至少不是全部。

这是后端同意的那些(据我所知,是 Scala Native):

  • 所有原始类型:BooleanCharByteShortIntLongFloatDoubleUnit
  • scala.Array
  • Cloneable(Scala Native 目前不支持,参见#334
  • StringStringBuilder(主要用于字符串连接)
  • Object,几乎所有的方法

以下是他们不同意的地方:

  • 原始类型的盒装版本(例如java.lang.Integer
  • Serializable
  • java.rmi.Remotejava.rmi.RemoteException
  • scala.annotation.* 中的一些注解(例如,strictfp
  • java.lang.reflect.* 中的一些东西,被 Scala/JVM 用来实现结构类型

此外,虽然本身不​​是类型,但a long list of primitive methods 也由后端专门处理。

平台特定类型

除了上面提到的在所有平台上都可用的类型之外,非 JVM 平台还添加了自己的特殊类型以实现互操作性。

Scala.js 特定类型

JSDefinitions.scala

  • js.Any:概念上是Any 的第三个子类型,除了AnyValAnyRef。它们具有 JavaScript 语义而不是 Scala 语义。
  • String 和所有原始类型的盒装版本(被编译器大量重写——所谓的“劫持”)
  • js.ThisFunctionN:他们的 apply 方法与其他 JavaScript 类型的行为不同(第一个实际参数成为被调用函数的 thisArgument
  • js.UndefOrjs.|(尽管它们没有扩展 js.Any,但它们的行为类似于 JS 类型)
  • js.Objectnew js.Object() 特例为空 JS 对象字面量 {}
  • js.JavaScriptException(在throwcatch 中表现得非常特别)
  • js.WrappedArray(用于 varargs 的脱糖)
  • js.ConstructorTag(类似于ClassTag
  • 注解js.native,以及js.annotation.*中的所有注解

另外,还有十几个primitive methods

Scala 原生特定类型

NirDefinitions.scala

  • 无符号整数:UByteUShortUIntULong
  • Ptr,指针类型
  • FunctionPtrN,函数指针类型
  • native.* 中的注解
  • scala.scalanative.runtime 中的一些额外的原始方法

【讨论】:

  • 感谢您的慷慨回答。稍后,我可能会附加一个关于 Predef 的 Privileged 部分。
  • @som-snytt 我还添加了一个特定于平台的特殊类型列表。
  • 能否详细说明:SAM treatment of anonymous functions?什么是SAM治疗?
  • SAM 处理是将 FunctionN 视为常规的单一抽象方法特征,类似于 Runnable 等其他特征。在 2.12 中,您可以使用匿名函数代替 SAM 类型的值,因此 FunctionN 作为匿名函数的唯一类型已经失去了大部分“特殊地位”。
  • OptionTupleN 不再是模式匹配所特有的。模式匹配现在是结构化的,接受任何{ def isEmpty: Boolean; def get: T },其中T,如果它有名为_1 的成员等被视为一个元组,否则被视为一个值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-31
  • 2017-05-03
  • 1970-01-01
  • 2011-06-09
  • 2021-11-14
相关资源
最近更新 更多