Skip to content
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
@sir-wabbit

Description

@sir-wabbit

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions