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

问题描述 投票:2回答:1

我正在学习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的消息,并发现所有的desugaring都是在第一阶段进行的:

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"和最终的desugared版本

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

以后为什么暗示会被贬低?或者它是如何工作的?

scala compilation implicit
1个回答
2
投票

暗示不是“贬低”。 “desugar”这个词源于“语法糖”这个词。注意“语法糖”中的“句法”部分。这意味着这种转换可以在非常低的语法层面上进行。例如,为了desugar

val Ext(i) = ten

变成类似的东西

val i = Ext.unapply(ten).get

你不必知道关于Extteni类型的任何信息。您甚至不必知道这些符号是否存在于范围内。你接受了原始语法片段,并对它们进行了重新排序,这就是全部。

(我添加了get,因为否则类型不匹配,由scala -print打印的实际desugared代码是非常可怕的)


搜索implicits是非常不同的。它至关重要地取决于所有符号和方法签名都已得到解决的事实,以及所有类型的所有子表达式都已得出[脚注1]。这是因为:

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

这两种信息都不存在于程序的原始语法结构中,并且首先要在后面的阶段中重构。这就是为什么隐含的解决方案必须在纯粹的句法脱臼之后。

[脚注1]这是一个过于简单化的问题:在插入一些含义之后,类型检测器必须以某种方式推断出更多信息,所以似乎这些阶段必须交织在一起。

© www.soinside.com 2019 - 2024. All rights reserved.