Lambdas 的 Scala 隐式转换

Scala Implicit conversion for Lambdas

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

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 Transaction 更改为 implicit val thisTransaction = new Transaction 并将 op(trans) 更改为 op 它不起作用。

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

opTransaction => T 类型,而不是(不幸的是,我认为不可能指定它)implicit Transaction => T.

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

计划在 Scala 的未来版本中使用隐式函数类型。据我所知,连下一个版本(2.13)都没有。

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

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

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

我想从博客的介绍中应该很清楚post,这是Odersky为了消除Dotty编译器实现中的一些样板而发明的新特性,引用:

For instance in the dotty compiler, almost every function takes an implicit context parameter which defines all elements relating to the current state of the compilation.

目前Scala的主流版本好像没有这个。


编辑

(在评论中回答 follow-up 问题)

如果我对博客 post 的理解正确,它会被脱糖成类似

的内容
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[...]{} 是一个匿名本地 class。基本 class ImplicitFunction1 是这个新功能,它类似于普通 lambda 的 Function,但有 implicit 个参数。