On Thursday, 28 October 2021 at 13:30:53 UTC, Paul Backus wrote:
On Thursday, 28 October 2021 at 09:02:52 UTC, JG wrote:
I am heavily using SumType (which I like very much). The
problem I am having is that is seems to be causing slow
compile times (as can be observed by profiling during the
compile). The problem seems to be with match (which is
extremely convenient to use). I looked at the code and it does
the only reasonable thing too do which is to test each handler
against each type. The slow compile time makes development
slower and less pleasant, so I am thinking of replacing
SumType with my own tagged union and writing out the switches
by hand. However, I really don't like this idea since it makes
the code less readable and more prone to errors. Any
suggestions?
Hi, I'm the author of `SumType`. Thanks for bringing this to my
attention. The good news is, I have not put a lot of effort so
far into micro-optimizing the compile-time performance of
`match`, so there is almost certainly room for improvement.
If you have an example of the kind of code you are seeing poor
compile-time performance for, I'd be happy to use it as a
benchmark/profiling target. Any profiling data you've collected
would also be helpful.
I've created issues for this on Bugzilla and the sumtype Github
repository:
https://issues.dlang.org/show_bug.cgi?id=22447
https://github.com/pbackus/sumtype/issues/76
Thank you so much for your response (and thanks for the hard work
that went into SumType). Here is a rather contrived example which
compiles in around 9 seconds on my machine.
import std;
struct A1 {int val; }
struct A2 {int val; }
struct A3 {int val; }
struct A4 {int val; }
struct A5 {int val; }
struct A6 {int val; }
struct A7 {int val; }
struct A8 {int val; }
struct A9 {int val; }
struct A10 {int val; }
struct A11 {int val; }
struct A12 {int val; }
struct A13 {int val; }
struct A14 {int val; }
alias A =
SumType!(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14);
T asserter(T)() { assert(0); }
auto op(A1 x, A1 y, A1 z) { return x.val + y.val + z.val; }
auto op(A2 x, A2 y, A2 z) { return x.val + y.val - z.val; }
auto op(A3 x, A3 y, A3 z) { return x.val + y.val * z.val; }
auto op(A4 x, A4 y, A4 z) { return x.val + y.val & z.val; }
auto op(A5 x, A5 y, A5 z) { return x.val - y.val + z.val; }
auto op(A6 x, A6 y, A6 z) { return x.val - y.val - z.val; }
auto op(A7 x, A7 y, A7 z) { return x.val - y.val * z.val; }
auto op(A8 x, A8 y, A8 z) { return x.val - y.val & z.val; }
auto op(A9 x, A9 y, A9 z) { return x.val * y.val + z.val; }
auto op(A10 x, A10 y, A10 z) { return x.val * y.val - z.val; }
auto op(A11 x, A11 y, A11 z) { return x.val * y.val * z.val; }
auto op(A12 x, A12 y, A12 z) { return x.val * y.val & z.val; }
auto op(A13 x, A13 y, A13 z) { return x.val & y.val + z.val; }
auto op(A14 x, A14 y, A14 z) { return x.val & y.val - z.val; }
auto op(A a, A b, A c) {
return a.match!(
x=>b.match!(
y=>c.match!(z=>op(x,y,z),
_=>asserter!int),
_=>asserter!int));
}
auto op2(A a, A b, A c) {
alias doMatch = match!(
(x, y, z) => op(x,y,z),
(_1, _2, _3) => asserter!int
);
return doMatch(a, b, c);
}
void main()
{
A a = A1(12);
A b = A1(13);
A c = A1(14);
assert(op(a,b,c)==39);
assert(op2(a,b,c)==39);
}