<div dir="ltr"><div dir="ltr">On Fri, Apr 24, 2020 at 2:20 PM Walter Bright via Digitalmars-d <<a href="mailto:digitalmars-d@puremagic.com">digitalmars-d@puremagic.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 4/22/2020 5:04 AM, Manu wrote:<br>
> [...]<br>
<br>
Ok, I've had a chance to think about it. It's a scathingly brilliant idea!<br>
<br>
But (there's always a but!) something stuck out at me. Consider arrays:<br>
<br>
<br>
void test()<br>
{<br>
     auto a = [1, 2, 3];<br>
     int[3] b = a[]*a[]; // b[0] = a[0]*a[0]; b[1] = a[1]*a[1]; b[2] = a[2]*a[2];<br>
     int[3] c = a[]*2; // c[0] = a[0]*2; c[1] = a[1]*2; c[2] = a[2]*2;<br>
}<br>
<br>
These look familiar! D tuples already use array syntax - they can be indexed and <br>
sliced. Instead of the ... syntax, just use array syntax!<br>
<br>
The examples from the DIP:<br>
<br>
=====================================<br>
--- DIP<br>
(Tup*10)...  -->  ( Tup[0]*10, Tup[1]*10, ... , Tup[$-1]*10 )<br>
<br>
--- Array syntax<br>
Tup*10<br>
<br>
====================================<br>
--- DIP<br>
alias Tup = AliasSeq!(1, 2, 3);<br>
int[] myArr;<br>
assert([ myArr[Tup + 1]... ] == [ myArr[Tup[0] + 1], myArr[Tup[1] + 1], <br>
myArr[Tup[2] + 1] ]);<br>
<br>
--- Array<br>
alias Tup = AliasSeq!(1, 2, 3);<br>
int[] myArr;<br>
assert([ myArr[Tup + 1] ] == [ myArr[Tup[0] + 1], myArr[Tup[1] + 1], <br>
myArr[Tup[2] + 1] ]);<br>
<br>
===================================<br>
---DIP<br>
alias Values = AliasSeq!(1, 2, 3);<br>
alias Types = AliasSeq!(int, short, float);<br>
pragma(msg, cast(Types)Values...);<br>
<br>
---Array<br>
alias Values = AliasSeq!(1, 2, 3);<br>
alias Types = AliasSeq!(int, short, float);<br>
pragma(msg, cast(Types)Values);<br>
<br>
=================================<br>
---DIP<br>
alias OnlyTwo = AliasSeq!(10, 20);<br>
pragma(msg, (Values + OnlyTwo)...);<br>
<br>
---Array<br>
alias OnlyTwo = AliasSeq!(10, 20);<br>
pragma(msg, Values + OnlyTwo);<br>
<br>
<br>
The idea is simply if we have:<br>
<br>
     t op c<br>
<br>
where t is a tuple and c is not, the result is:<br>
<br>
    tuple(t[0] op c, t[1] op c, ..., t[length - 1] op c)<br>
<br>
For:<br>
<br>
     t1 op t2<br>
<br>
the result is:<br>
<br>
    tuple(t1[0] op t2[0], t1[1] op t2[1], ..., t1[length - 1] op t2[length - 1])<br>
<br>
The AST doesn't have to be walked to make this work, just do it as part of the <br>
usual bottom-up semantic processing.<br></blockquote><div><br></div><div>I thought about this, but this reaches much further than `a op b `.</div><div></div><div>When I considered your approach, it appeared to add a lot of edges and limits on the structure of the expressions, particularly where it interacts with var-args or variadic templates.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
The advantage is:<br>
<br>
1. no new grammar<br></blockquote><div><br></div><div>Fortunately, the grammar is trivial.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
2. no new operator precedence rules<br>
3. turn expressions that are currently errors into doing the obvious thing<br></blockquote><div><br></div><div>This is compelling, but I couldn't think how it can work from end to end.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Why does C++ use ... rather than array syntax? Because C++ doesn't have arrays!<br></blockquote><div><br></div><div>Another reason I introduce `...` is for static fold.</div><div>The follow-up to this DIP would make this expression work:</div><div><br></div><div>  `Tup + ...`  ->  `Tup[0] + Tup[1] + ... + Tup[$-1]`</div><div><br></div><div></div><div>For instance, up-thread it was noted that a static-fold algorithm may implement a find-type-in-tuple; it would look like this:</div><div>  `is(MyType == Types) || ...`  <- evaluate `true` if MyType is present in Types with no template instantiation junk.</div><div><br></div><div>So, the `...` is deliberately intended to being additional value.</div><div><br></div><div><br></div><div>Can you show how your suggestion applies to some more complex cases (not yet noted in the DIP).</div><div><br></div><div>// controlled expansion:</div><div>alias Tup = AliasSeq!(0, 1, 2);</div><div></div><div>alias Tup2 = AliasSeq!(3, 4, 5);</div><div></div><div>[ Tup, Tup2... ]...  ->  

[ 0, 3, 4, 5 ], 

[ 1, 3, 4, 5  ], 

[ 2, 3, 4, 5 ]<br></div><div><br></div><div>// template instantiations</div><div>alias TTup = AliasSeq!(int, float, char);</div><div></div><div>MyTemplate!(Tup, TTup.sizeof...)...  -> 

MyTemplate!(0, 4, 4, 1), 

MyTemplate!(1, 4, 4, 1), 

MyTemplate!(2, 4, 4, 1)<br></div><div><br></div><div>// replace staticMap</div><div>alias staticMap(alias F, T...) = F!T...;</div><div><br></div><div>// more controlled expansion, with template arg lists</div><div>AliasSeq!(10, Tup, 20)...  -> ( 10, 0, 20, 10, 1, 20, 10, 2, 20 )<br></div><div>AliasSeq!(10, Tup..., 20)  -> ( 10, 0, 1, 2, 20 )</div><div><br></div><div>// static fold (outside the scope of this DIP, but it's next in line)</div><div><div>`Tup + ...`  ->  `Tup[0] + Tup[1] + ... + Tup[$-1]`</div><div><br></div><div>// static find</div><div>`is(MyType == Types) || ...`<br></div><div><br></div><div>That said, with respect to these fold expressions, it would be ideal if they applied to arrays equally as I propose to tuples.</div><div></div></div></div></div>