This repository was archived by the owner on Nov 29, 2020. It is now read-only.
This repository was archived by the owner on Nov 29, 2020. It is now read-only.
Instance instantiation in the outermost scope #38
Open
Description
For future docs:
Instance instantiation in the outermost scope
Consider the following snippet:
implicit def eqList[A](implicit A: Eq[A]): Eq[List[A]] =
new Eq[A] { ... }
implicit class EqOps[A](value: A) {
def ===(other: A)(implicit A: Eq[A]): Boolean = A.equal(value, other)
}
...
object Test {
def test: Unit = {
val a : List[Int] = ...
val b : List[Int] = ...
for (i < 0 until 100) {
a === b
}
}
}
The body of the loop will compile to:
new EqOps(a).===(b)(eqList(eqInt))
So there are two allocations per comparison, one allocation of the syntax extension class and one for the instance of Eq[List[A]]
. This optimization should fix the latter by instantiating the instance in the outermost static scope,
object Test {
implicit val $ev1: Eq[List[A]] = eqList(eqInt)
def test: Unit = {
val a : List[Int] = ...
val b : List[Int] = ...
for (i < 0 until 100) {
new EqOps(a).===(b)($ev1)
}
}
}
or at the beginning of the function:
class Test {
def test: Unit = {
implicit val $ev1: Eq[List[A]] = eqList(eqInt)
val a : List[Int] = ...
val b : List[Int] = ...
for (i < 0 until 100) {
new EqOps(a).===(b)($ev1)
}
}
}
Requirements
- No side-effects in implicits.