scala - 隐式方法参数解析? Scala 编译器?

标签 scala compilation implicit

我正在学习 Scala 中的隐式方法。例如,考虑以下测试代码:

object Test{
  def main(args: Array[String]) = {
    implicit val f: Int => String = (_: Int).toString + "sdgfdfsg"
    val Ext(i) = 10
    println(i)
  }
}


object Ext{
  def unapply(i: Int)(implicit f: Int => String): Option[String] = Some(f(i))
}

此代码按预期工作。但我不清楚的是它为什么有效。所以我读到了 Scala compiler phases 并发现所有脱糖都是在第一阶段进行的:

parser   1  parse source into ASTs, perform simple desugaring

但是脱糖的顺序是什么?在示例中似乎

val Ext(i) = 10

首先脱糖为

val i = Ext.unapply(10)

然后编译器找到隐式值implicit val f: Int => String = (_: Int).toString + "sdgfdfsg" 最终脱糖版本为

val i = Ext.unapply(10)(f)

为什么稍后要对隐式进行脱糖处理?或者它是如何工作的?

最佳答案

隐式并未“脱糖”。 “脱糖”一词源于“语法糖”这一表达方式。注意“语法糖”中的“语法”部分。这意味着这种转换可以发生在非常低​​的句法级别上。比如为了脱糖

val Ext(i) = ten

变成类似的东西

val i = Ext.unapply(ten).get

您不必了解 Ext 的类型。 ,或ten ,或i 。您甚至不必知道这些符号是否存在于作用域中。您获取原始语法片段,然后对它们进行一些重新排序,仅此而已。

(我添加了get,因为否则类型不匹配,scala -print打印的实际脱糖代码明显更可怕)


搜索implicit s 是非常不同的。它关键取决于以下事实:所有符号和方法签名均已解析,并且所有子表达式的所有类型均已派生[脚注 1]。这是因为:

  • 必须解析符号,否则编译器甚至不知道方法 unapply在对象上Ext需要额外的隐式参数。
  • 类型必须已知,否则它将不知道要搜索什么类型的隐式。

这两种信息都不存在于程序的原始语法结构中,并且必须首先在后续阶段中重建。这就是为什么隐式解析必须在纯粹的语法脱糖之后进行。

[脚注 1] 这过于简单化了:在插入一些隐式后,类型检查器必须以某种方式推断出更多信息,因此这些阶段似乎必须交织在一起。

关于scala - 隐式方法参数解析? Scala 编译器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49094615/

相关文章:

scala - Play Websocket示例-仅一位Akka Actor ?

使用 make 在 linux 上编译驱动程序

linux - 如何配置 makefile?

java - Play Framework 2.3.8 编译错误

Scala,我可以将类构造函数参数(未定义为隐式)作为隐式值传递吗?

c - 即使添加了 #include <stdio.h> 也隐式声明了 popen

scala - 你可以模拟一个值而不是一个方法吗?

scala - 如何在 Scala 中获取与类参数同名的字段?

scala - Scala类型系统:基本类型不匹配

scala - 什么是隐式对象?