I am trying to understand the implicit function types from the link - http://www.scala-lang.org/blog/2016/12/07/implicit-function-types.html and below is a sample code as example. In the below code we first create a class 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
}
}
Next I define two methods f1 and f2 as shown below
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
}
Then a method is defined to invoke the functions
def transaction[T](op: Transaction => T) = {
val trans: Transaction = new Transaction
op(trans)
trans.commit()
}
Below lambda is used to invoke the code
transaction {
implicit thisTransaction =>
val res = f1(3)
println(if (thisTransaction.isAborted) "aborted" else s"result: $res")
}
My question is if I change the val trans: Transaction = new Transaction
to implicit val thisTransaction = new Transaction
and change op(trans)
to op
it is not working.
I am not able to understand why even if thisTransaction of type Transaction is present in the scope it is not being used?
This here compiles just fine with dotty 0.4.0-RC1:
def transaction[T](op: implicit Transaction => T) = {
implicit val trans: Transaction = new Transaction
op
trans.commit()
}
I think it should be clear from the introduction of the blog post that this is a new feature that Odersky invented to eliminate some boilerplate in the implementation of the Dotty compiler, quote:
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.
This seems to be currently not available in the mainstream versions of Scala.
EDIT
(answer to follow-up question in the comment)
If I understood the blog post correctly, it is desugared into something like
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")
}
}
)
the new ImplicitFunction1[...]{}
is an anonymous local class. The base class ImplicitFunction1
is this new feature, which is similar to the Function
for ordinary lambdas, but with implicit
arguments.