0

我试图从链接中了解隐式函数类型 - http://www.scala-lang.org/blog/2016/12/07/implicit-function-types.html以下是示例代码作为示例。在下面的代码中,我们首先创建一个类 Transaction。

class Transaction {
  private val log = scala.collection.mutable.ListBuffer.empty[String]
  def println(s: String): Unit = log += s

  private var aborted = false
  private var committed = false

  def abort(): Unit = { aborted = true }
  def isAborted = aborted

  def commit(): Unit =
  if (!aborted && !committed) {
     Console.println("******* log ********")
     log.foreach(Console.println)
     committed = true
  }
}

接下来我定义了两个方法 f1 和 f2 如下所示

def f1(x: Int)(implicit thisTransaction: Transaction): Int = {
  thisTransaction.println(s"first step: $x")
  f2(x + 1)
}
def f2(x: Int)(implicit thisTransaction: Transaction): Int = {
  thisTransaction.println(s"second step: $x")
  x
}

然后定义一个方法来调用函数

def transaction[T](op: Transaction => T) = {
  val trans: Transaction = new Transaction
  op(trans)
  trans.commit()
}

下面的 lambda 用于调用代码

transaction {
    implicit thisTransaction =>
      val res = f1(3)
      println(if (thisTransaction.isAborted) "aborted" else s"result: $res")
}  

我的问题是,如果我更改val trans: Transaction = new Transactionimplicit val thisTransaction = new Transaction并更改op(trans)op它不起作用。

我无法理解为什么即使 Transaction 类型的 thisTransaction 存在于它没有被使用的范围内?

4

3 回答 3

2

隐式函数类型计划用于 Scala 的未来版本。据我所知,甚至没有下一个版本(2.13)。

目前,您只能在Dotty中使用它们。

于 2018-04-06T11:49:53.927 回答
1

op是类型Transaction => T,而不是(不幸的是,我认为不可能指定这一点)implicit Transaction => T

所以它的类型参数Transaction不能隐式提供。它必须是一个显式参数。(只有标记的参数列表中的函数的参数implicit才能隐式提供。)

于 2018-04-06T11:38:50.990 回答
1

这在这里用dotty 0.4.0-RC1编译得很好:

def transaction[T](op: implicit Transaction => T) = {
  implicit val trans: Transaction = new Transaction
  op
  trans.commit()
}

我认为从博客文章的介绍中应该清楚,这是 Odersky 发明的一个新功能,用于消除 Dotty 编译器实现中的一些样板,引用:

例如,在 dotty 编译器中,几乎每个函数都采用隐式上下文参数,该参数定义与当前编译状态相关的所有元素。

这似乎目前在 Scala 的主流版本中不可用。


编辑

(回答评论中的后续问题)

如果我正确理解了博客文章,它就会被脱糖成类似的东西

transaction(
  new ImplicitFunction1[Transaction, Unit] {
    def apply(implicit thisTransaction: Transaction): Unit = {
      val res = f1(args.length)(implicit thisTransaction:Transaction) 
      println(if (thisTransaction.isAborted) "aborted" else s"result: $res")
    }
  } 
)

new ImplicitFunction1[...]{}是一个匿名的本地类。基类ImplicitFunction1是这个新特性,它类似于Function普通的 lambda,但带有implicit参数。

于 2018-04-06T12:25:12.030 回答