April 23, 2020
On 4/23/20 9:53 AM, Manu wrote:

> 
> You can do this by expanding tuples with the appropriate indices:
>    fun(Xs[CrossIndexX], Ys[CrossIndexY])...
> Where CrossIndexX is (0, 0, 1, 1) and CrossIndexY is (0, 1, 0, 1).

I don't think this works, aren't Xs and Ys tuples also?

I think what you need is to expand the Xs and Ys into further tuples:

alias XParams = Xs[CrossIndexX]...;
alias YParams = Ys[CrossIndexY]...;
fun(XParams, YParams)...;

Which would work I think.

this means you need 4 pre-expression declarations! Two for the X and Y expansions, and two for the indexes.

-Steve
April 23, 2020
On 4/23/20 11:39 AM, Mafi wrote:
> On Thursday, 23 April 2020 at 15:11:16 UTC, Stefan Koch wrote:
>> On Thursday, 23 April 2020 at 15:06:51 UTC, Mafi wrote:
>>> On Thursday, 23 April 2020 at 12:43:59 UTC, Simen Kjærås wrote:
>>>> [...]
>>>
>>> I think ...-Expressions should first expand nested ...-Expressions (or equivalently explicitly ignore nested ...-Expressions). Then the cross-product can be expressed as:
>>>
>>> template crossHelper(F, X, Y...) {
>>>   alias crossHelper = F(X, Y)...;
>>> }
>>>
>>> crossHelper!(S, X, Y...)...
>>>
>>> => S!(X[0], Y[0]), S!(X[1], Y[0]), ..., S!(X[n-1], X[m-1])
>>>
>>> because the nested expression Y... is expanded first resulting in crossHelper!(S, X, Y[0]), ..., crossHelper!(S, X, Y[m-1]) which then has the X expanded.
>>
>> that won't work.
>> F is a type parameter in crossHelper.
> 
> Well, then what about:
> 
> template crossHelper(alias F, X, Y...) {
>    alias crossHelper = F!(X, Y)...;
> }
> 
> crossHelper!(S, X, Y...)...

In this call, Y... does nothing, it just trivially means Y, so you really have:

crossHelper!(S, X, Y)...

Note here that X and Y are the parameters, not the inner template instantations. Let's unconfuse this, and see what we really are talking about. Let's say we want to do A cross B:

crossHelper!(S, A, B)...

Now, A[0] will map to X in the template, and AliasSeq!(A[1 .. $], B) will map to Y. So this is not what you want. Tuple lists automatically flatten, and there can only be one variadic.

In order to capture 2 tuples as template parameters, you need a nested template.

For instance:

template crossHelper(alias F, X...) {
   template c(Y...) {
      // in here, you have X as a tuple and Y as a tuple
   }
}

Called like:

crossHelper!(S, A).c!(B);

Not as nice as one would like. But I think it would be a requirement.

-Steve
April 23, 2020
On Thursday, 23 April 2020 at 16:40:05 UTC, Steven Schveighoffer wrote:
>
> crossHelper!(S, A).c!(B);
>
> Not as nice as one would like. But I think it would be a requirement.
>
> -Steve

As long as we don't allow tuples of tuples yes.

When we allow tuples of tuples many nice things can happen
but it wouldn't play as nicely with current language rules.
April 23, 2020
On Thursday, 23 April 2020 at 16:40:05 UTC, Steven Schveighoffer wrote:
> On 4/23/20 11:39 AM, Mafi wrote:
>> 
>> Well, then what about:
>> 
>> template crossHelper(alias F, X, Y...) {
>>    alias crossHelper = F!(X, Y)...;
>> }
>> 
>> crossHelper!(S, X, Y...)...
>
> In this call, Y... does nothing, it just trivially means Y, so you really have:

This is wrong under the assumption I wrote before: nested ...-expressions are expanded first!

To explain in more detail what I mean: Let A be the sequence (101, 102, 103) and B be (201, 202, 203). Then F!(A, B)... is (F!(101, 201), F!(102, 202), F!(103, 203)) analoguous to simultaneous expansion in C++ and as explained in the DIP draft.

But of course:

F!(A, B[0], B[1], B[2])... is (F!(101, 201, 202, 203), F!(102, 201, 202, 203), F!(103, 201, 202, 203))

So if ...-expansions are expanded inside out then:

F!(A, B...)... is F!(A, B[0], B[1], B[2])... is (F!(101, 201, 202, 203), F!(102, 201, 202, 203), F!(103, 201, 202, 203))

this can exploited to implement cross product using my helper I wrote above.

April 23, 2020
On 4/23/20 1:44 PM, Mafi wrote:
> On Thursday, 23 April 2020 at 16:40:05 UTC, Steven Schveighoffer wrote:
>> On 4/23/20 11:39 AM, Mafi wrote:
>>>
>>> Well, then what about:
>>>
>>> template crossHelper(alias F, X, Y...) {
>>>    alias crossHelper = F!(X, Y)...;
>>> }
>>>
>>> crossHelper!(S, X, Y...)...
>>
>> In this call, Y... does nothing, it just trivially means Y, so you really have:
> 
> This is wrong under the assumption I wrote before: nested ....-expressions are expanded first!
> 
> To explain in more detail what I mean: Let A be the sequence (101, 102, 103) and B be (201, 202, 203). Then F!(A, B)... is (F!(101, 201), F!(102, 202), F!(103, 203)) analoguous to simultaneous expansion in C++ and as explained in the DIP draft.
> 
> But of course:
> 
> F!(A, B[0], B[1], B[2])... is (F!(101, 201, 202, 203), F!(102, 201, 202, 203), F!(103, 201, 202, 203))
> 
> So if ...-expansions are expanded inside out then:
> 
> F!(A, B...)... is F!(A, B[0], B[1], B[2])... is (F!(101, 201, 202, 203), F!(102, 201, 202, 203), F!(103, 201, 202, 203))
> 
> this can exploited to implement cross product using my helper I wrote above.
> 

What you are asking for is that B is expanded into "not-a-tuple" before the outer expression is expanded. I don't think that's the plan, I think SomeTuple... expands to SomeTuple.

What I think the DIP is going to do is expand B first into a tuple, and then that tuple is now expanded the same as F!(A, B)....

But maybe I'm wrong? For sure more clarification is needed on nested expansion.

-Steve
April 23, 2020
On Thursday, 23 April 2020 at 18:05:07 UTC, Steven Schveighoffer wrote:
> On 4/23/20 1:44 PM, Mafi wrote:
>> [...]
>
> What you are asking for is that B is expanded into "not-a-tuple" before the outer expression is expanded. I don't think that's the plan, I think SomeTuple... expands to SomeTuple.
>
> What I think the DIP is going to do is expand B first into a tuple, and then that tuple is now expanded the same as F!(A, B)....
>
> But maybe I'm wrong? For sure more clarification is needed on nested expansion.
>
> -Steve

If you post a complete example I can run it, at show you what happens.
I would say inner tuples expand first since that's how evaluating an expression tree works
you start with the innermost expressions.
April 23, 2020
On 4/23/20 2:18 PM, Stefan Koch wrote:
> On Thursday, 23 April 2020 at 18:05:07 UTC, Steven Schveighoffer wrote:
>> On 4/23/20 1:44 PM, Mafi wrote:
>>> [...]
>>
>> What you are asking for is that B is expanded into "not-a-tuple" before the outer expression is expanded. I don't think that's the plan, I think SomeTuple... expands to SomeTuple.
>>
>> What I think the DIP is going to do is expand B first into a tuple, and then that tuple is now expanded the same as F!(A, B)....
>>
>> But maybe I'm wrong? For sure more clarification is needed on nested expansion.
>>
> 
> If you post a complete example I can run it, at show you what happens.
> I would say inner tuples expand first since that's how evaluating an expression tree works
> you start with the innermost expressions.

The question is whether the expanded inner expression is considered a tuple for expansion later or not.

alias tuple1 = AliasSeq!(1, 2, 3);
alias tuple2 = AliasSeq!(4, 5, 6);
pragma(msg, [AliasSeq!(tuple1..., tuple2)...]);

If it expands tuple1 first, then expands tuple 2 without re-expanding the result of tuple1..., then it should be:

[1, 2, 3, 4, 1, 2, 3, 5, 1, 2, 3, 6]

If it expands both tuple1 and tuple2 together, it should be:

[1, 4, 2, 5, 3, 6]

-Steve
April 23, 2020
On Thursday, 23 April 2020 at 18:57:04 UTC, Steven Schveighoffer wrote:
> On 4/23/20 2:18 PM, Stefan Koch wrote:
>> [...]
>
> The question is whether the expanded inner expression is considered a tuple for expansion later or not.
>
> alias tuple1 = AliasSeq!(1, 2, 3);
> alias tuple2 = AliasSeq!(4, 5, 6);
> pragma(msg, [AliasSeq!(tuple1..., tuple2)...]);
>
> If it expands tuple1 first, then expands tuple 2 without re-expanding the result of tuple1..., then it should be:
>
> [1, 2, 3, 4, 1, 2, 3, 5, 1, 2, 3, 6]
>
> If it expands both tuple1 and tuple2 together, it should be:
>
> [1, 4, 2, 5, 3, 6]
>
> -Steve

It's the latter.
you cannot re-expand.
April 23, 2020
On 4/23/20 3:02 PM, Stefan Koch wrote:
> On Thursday, 23 April 2020 at 18:57:04 UTC, Steven Schveighoffer wrote:
>> On 4/23/20 2:18 PM, Stefan Koch wrote:
>>> [...]
>>
>> The question is whether the expanded inner expression is considered a tuple for expansion later or not.
>>
>> alias tuple1 = AliasSeq!(1, 2, 3);
>> alias tuple2 = AliasSeq!(4, 5, 6);
>> pragma(msg, [AliasSeq!(tuple1..., tuple2)...]);
>>
>> If it expands tuple1 first, then expands tuple 2 without re-expanding the result of tuple1..., then it should be:
>>
>> [1, 2, 3, 4, 1, 2, 3, 5, 1, 2, 3, 6]
>>
>> If it expands both tuple1 and tuple2 together, it should be:
>>
>> [1, 4, 2, 5, 3, 6]
>>
> 
> It's the latter.
> you cannot re-expand.

Those 2 are contradictory statements.

If it's the latter, then tuple1... is expanded to a tuple that is then used in the outer expansion.

-Steve
April 23, 2020
On Thursday, 23 April 2020 at 19:27:31 UTC, Steven Schveighoffer wrote:
> On 4/23/20 3:02 PM, Stefan Koch wrote:
>> On Thursday, 23 April 2020 at 18:57:04 UTC, Steven Schveighoffer wrote:
>>>[...]
>> 
>> It's the latter.
>> you cannot re-expand.
>
> Those 2 are contradictory statements.
>
> If it's the latter, then tuple1... is expanded to a tuple that is then used in the outer expansion.
>
> -Steve

k tuples with n elements can only expand to 1 tuple with k*n elements.
They can't get more.