Scala对Lambdas的隐式转换

时间:2018-04-06 10:53:22

标签: scala lambda dotty

我试图从链接中理解隐式函数类型 - 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 Transaction更改为implicit val thisTransaction = new Transaction并将op(trans)更改为op则无效。

我无法理解为什么即使在范围内存在此类事务的事务,它还没有被使用?

3 个答案:

答案 0 :(得分:1)

op的类型为Transaction => T,而不是(我认为不可能指定此内容)implicit Transaction => T

因此无法隐式提供类型Transaction的参数。它必须是一个明确的论点。 (只能隐式提供标记为implicit的参数列表中的函数的参数。)

答案 1 :(得分:1)

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

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

答案 2 :(得分: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是这个新功能,类似于普通lambda的Function,但带有implicit个参数。