magnolia icon indicating copy to clipboard operation
magnolia copied to clipboard

Wish list: Support inlined dispatch/combine calls

Open neko-kai opened this issue 5 years ago • 5 comments

Theoretically it may be possible to generalize CaseClass/SealedTrait structures to put trees in there instead of runtime values and parameterize the Magnolia macro with dispatch/combine before creating the macro, e.g.

trait MyTC[A] {
  def toMap(a: A): Map[String, String]
}
object MyTC {
  def derived[A] = macro MyMagnoliaDeriver.gen[A]
}

object MyMagnoliaDeriver {
  def gen[A: c.WeakTypeTag](c: whitebox.Context): c.Expr[MyTC[A]] = {
    Magnolia.hypotheticalGenWith[MyTC[A]](combine[A](c), dispatch[A](c))
  }

  def combine[Type: c.WeakTypeTag](c: whitebox.Context)(
    caseclass: CaseClass[c.Expr, MyTC, Type]
  ): c.Expr[MyTC[Type]] = {
    import c.universe._
    val arg = c.Expr[Type](TermName("arg"))
    val exprs = ctx.parameters.map { p =>
      reify { p.label.splice -> p.typeclass.splice.toMap(p.dereference(arg).splice) }
    }.toList
    val listExprs = c.Expr[List[(String, String)]] = q"$exprs"
    reify { 
      new TC[Type] {
        def toMap(arg: Type) = listExprs.splice.toMap
      }
    }
  }

  def dispatch = ...
}

This would allow to remove all the runtime cost for the creation of CaseClass/SealedTrait structures & inline all the information directly into the generated codecs

neko-kai avatar Apr 21 '20 14:04 neko-kai

I might need a bit longer to work out the implications of this... have you any idea what the runtime performance improvement might be? Obviously it would depend on what typeclass we're deriving, but a side-by-side comparison of a hand-rolled version of the derivation we could expect from this inlining against Magnoia's current derivation would be interesting...

propensive avatar Apr 23 '20 22:04 propensive

The point is to generate the exact same code for an instance as you would write if you hand-rolled it. Because you can output arbitrary trees in these functions you can optimize as much as you please - the difference is that you get some tricky reflection work pre-done and packed nicely into data types by Magnolia.

neko-kai avatar Apr 23 '20 22:04 neko-kai

Should be careful with inlining because you don't want to produce too big trees 😄 But it could be a feature for expert users.

joroKr21 avatar Apr 23 '20 23:04 joroKr21

Can this wait until Scala 3?

propensive avatar Dec 06 '20 00:12 propensive

Seems like it might happen automatically in 3 as long as user methods are inline

neko-kai avatar Dec 07 '20 13:12 neko-kai