On Thu, Apr 23, 2020 at 2:10 AM Steven Schveighoffer via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
On 4/22/20 11:17 AM, Manu wrote:
>
> I have thought about how to discuss this in the DIP; I describe the
> semantic, and what happens is what happens.
> This will work, and something will happen... when we implement
> TemplateInstance, we'll find out exactly what it is :P
> What I will do is show what such a nested tuple does when code works in
> the DIP to instantiate TemplateInstances.
>
> It's basically the same thing as what you showed above with:
> Items[0].MemberTup, Items[1].MemberTup, ...
> In general, in D currently, nested tuples flatten. Evaluate from the
> leaf upwards. Your answer will materialise.

I think this is more complicated than the MemberTup thing. By inference
of the name, MemberTup is a tuple, but only defined in the context of
the expanded items. There aren't any tuples for the compiler to expand
in there.

A template that returns a tuple based on it's parameters is a tuple with
or without expansion.

F!(F!t)) is valid. It's going to return int, char, int, char, int, char,
int, char

F!(F!t))... what does this do?

Saying "let's see what happens" is not a good way to create a DIP. We
have enough of "design by implementation" in D.

I only say that because;
1. It was 2am, and I had to think it through.
2. It will just apply the specification I've described in the DIP, absent of special-cases.

I expect it will do this: 

F!(F!t)... =>

expand for `t` (at leaf of tree):
F!( (F!t[0], F!t[1]) )  ~=   F!( (F!int, F!char) )  =>

Spec does not say it will NOW evaluate the template and operate on the result, it deals with the expression as stated.
If it didn't behave that way, it would be very easy to lead to recursive expansion expressions, and impossible to reason about the expansion when it disappears inside of code that's defined elsewhere.

Expansion applies to the expression as-written.

So, take the tuple from expanding `t`, and expand the next level:

( F!( (F!int, F!char)[0] ), F!( (F!int, F!char)[1] ) )  ~=    ( F!( F!int ), F!( F!char ) )

I think that's all the tuples in the expression, now semantic will run as usual, and it will resolve those templates:

Resolve inner F:

( F!(int, int), F!(char, char) )

And outer F:

( int, int, int, int, char, char, char, char )

That's the expansion I would expect from that expression. So, I guess the point you want to determine is that *evaluating* templates is NOT part of tuple expansion.
Template resolution will follow normally in semantic. The expansion applies to the expression as written, and I think that's the only possible definition, otherwise the expansion starts to recurse inside of implementation code which is defined elsewhere.

I think that expansion is actually reasonable and 'easy' to understand. There's nothing unexpected about application of the stated rules.
Of course, I would suggest not writing code like this, unless it's really clear to the reader what your intent was. There's a million-and-one ways to write obscure code that does something, but doesn't really help the reader along the way; this expression is one such thing.