Scala Неявное преобразование для Lambdas

Я пытаюсь понять неявные типы функций по ссылке - 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()
}

Ниже лямбда используется для вызова кода

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 это не работает.

Я не могу понять, почему, даже если thisTransaction типа Transaction присутствует в области, она не используется?

3 ответа

Решение

Это здесь хорошо компилируется с dotty 0.4.0-RC1:

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

Я думаю, из введения в блоге должно быть ясно, что это новая функция, которую Одерский изобрел, чтобы исключить какой-то шаблон при реализации компилятора 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 для обычных лямбд, но с implicit аргументы.

Неявные типы функций запланированы для будущей версии Scala. Насколько я знаю, нет даже следующей версии (2.13).

Пока вы можете использовать их только в Dotty.

op имеет тип Transaction => Tнет (и я не думаю, что это можно уточнить, к сожалению) implicit Transaction => T,

Так что его аргумент типа Transaction не может быть предоставлено неявно. Это должен быть явный аргумент. (Только аргументы для функции в списке аргументов помечены implicit могут быть предоставлены неявно.)

Другие вопросы по тегам