Optimize the number of `Transformer` instances during product transformations
arainko opened this issue · 0 comments
arainko commented
example:
import io.github.arainko.ducktape.*
import io.github.arainko.ducktape.Transformer.ForProduct
case class Person(int: Int, str: String, inside: Inside)
case class Person2(int: Int, str: String, inside: Inside2)
case class Inside(str: String, int: Int, inside: EvenMoreInside)
case class Inside2(int: Int, str: String, inside: EvenMoreInside2)
case class EvenMoreInside(str: String, int: Int)
case class EvenMoreInside2(str: String, int: Int)
val transformed = Person(1, "2", Inside("2", 1, EvenMoreInside("asd", 3))).to[Person2]
In the current version the generated code is kind of allocation heavy in regards to transformers, let's take a look at what is generated (Output of DebugMacros.code
):
to[Person](Person.apply(1, "2", Inside.apply("2", 1, EvenMoreInside.apply("asd", 3))))[Person2](
(((from: Person) =>
(new Person2(
int = from.int,
str = from.str,
inside = (
((`from₂`: Inside) =>
(new Inside2(
int = `from₂`.int,
str = `from₂`.str,
inside = (
((`from₃`: EvenMoreInside) =>
(new EvenMoreInside2(
str = `from₃`.str,
int = `from₃`.int
): EvenMoreInside2)): ForProduct[EvenMoreInside, EvenMoreInside2]
).transform(`from₂`.inside)
): Inside2)): ForProduct[Inside, Inside2]).transform(from.inside)): Person2)): ForProduct[Person, Person2])
)
We can see that for each 'sub-transformation' we allocate a new transformer to then just call transform
and get the result, we can simplify it by extracting the inside of the Transformer
lambda and calling it directly, so after optimizations this code should look like this:
to[Person](Person.apply(1, "2", Inside.apply("2", 1, EvenMoreInside.apply("asd", 3))))[Person2]((((from: Person) =>
(new Person2(
int = from.int,
str = from.str,
inside = new Inside2(
int = from.inside.int,
str = from.inside.str,
inside = new EvenMoreInside2(
str = from.inside.inside.str,
int = from.inside.inside.int
)
)
): Person2)
): ForProduct[Person, Person2]))
So pretty much something we'd write by hand, this optimization can also be done on ToAnyVal
and FromAnyVal
transformers.