I dun a DIP, possibly the best DIP ever

Mafi mafi at example.org
Fri Apr 24 09:01:59 UTC 2020


On Wednesday, 22 April 2020 at 12:04:30 UTC, Manu wrote:
> We have a compile time problem, and this is basically the cure. 
> Intuitively, people imagine CTFE is expensive (and it kinda 
> is), but really, the reason our compile times are bad is 
> template instantiation.
>
> This DIP single-handedly fixes compile-time issues in programs 
> I've written by reducing template instantiations by near-100%, 
> in particular, the expensive ones; recursive instantiations, 
> usually implementing some form of static map.
>
> https://github.com/dlang/DIPs/pull/188
>
> This is an RFC on a draft, but I'd like to submit it with a 
> reference implementation soon.
>
> Stefan Koch has helped me with a reference implementation, 
> which has so far
> gone surprisingly smoothly, and has shown 50x improvement in 
> compile times
> in some artificial tests.
> I expect much greater improvements in situations where 
> recursive template
> expansion reaches a practical threshold due to quadratic 
> resource
> consumption used by recursive expansions (junk template 
> instantiations, and
> explosive symbol name lengths).
> This should also drastically reduce compiler memory consumption 
> in
> meta-programming heavy applications.
>
> In addition to that, it's simple, terse, and reduces program 
> logic indirection via 'utility' template definitions, which I 
> find improves readability substantially.
>
> We should have done this a long time ago.
>
> - Manu

There is more corner cases to consider: AliasSeq-like members and 
tuple slicing.

What happens when a struct (or whatever) has a AliasSeq-like 
member, most prominently std.typecons.Tuple.expand.

Tuple!(short, int, long) t = tuple(short(1), int(2), long(3));

writeln(AliasSeq!("x", t.expand)); // => x 1 2 3
writeln(AliasSeq!("x", t.expand...)); // => x 1 2 3 
(unambiguously, although semantics already unclear)
writeln(AliasSeq!("x", t.expand)...); // => ? does the 
...-operator inspect the member to know it is a AliasSeq-like?
writeln(AliasSeq!("x", ((() => t)()).expand)...); // ?
writeln(AliasSeq!("x", ({
static if(t.expand == 1) {
return t
} else {
return tuple(4, 5, 6);
}
}()).expand)...); // it can't possibly expand here because the 
inner tuple already depends on the ..-expansion of t.expand == 1

The only sane way seems to be to treat .expand and any other 
member as opaque to-be-determined entity which is skipped by 
...-expansion. Otherwise you get a inconsistency between cases 3 
and 4/5. You have to explicitly opt-in by doing:

alias e = t.expand;
writeln(AliasSeq!("x", t.expand)); // => x 1 x 2 x 3

The other corner case is AliasSeq-slicing.

writeln(AliasSeq!("x", AliasSeq!(1, 2, 3))...); // no named 
sequence, no expansion => x 1 2 3
writeln(AliasSeq!("x", e)...); //named, therefore must be 
expansion => x 1 x 2 x 3
writeln(AliasSeq!("x", e[1..$])...); // ?

Is the last case of e[1..$] just an expression that happens to 
evaluate to an AliasSeq (like example here), or more like a named 
expression like example 2 here?

These cases also need to specified in the DIP.


More information about the Digitalmars-d mailing list