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
могут быть предоставлены неявно.)