<div dir="ltr"><div dir="ltr">On Wed, Oct 28, 2020 at 4:35 AM Andrei Alexandrescu 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">Incidentally I'm working on a book chapter on C++ variadics and just <br>
read through the standard <br>
(<a href="https://github.com/cplusplus/draft/blob/master/papers/n4140.pdf" rel="noreferrer" target="_blank">https://github.com/cplusplus/draft/blob/master/papers/n4140.pdf</a>, search <br>
for "variadic" and "pack"). It provides a good baseline for evaluating <br>
this proposal.<br>
<br>
Overall: the proposal is imprecise and needs a lot more fleshing out in <br>
order to provide an actual specification for implementation.<br>
<br>
Abstract: should not be an executive review consisting of only one <br>
confusing sentence ("..." is not an expression, it's punctuation or <br>
operator). Abstract should clarify how explicit tuple expansion compares <br>
with the existing implicit expansion.<br></blockquote><div><br></div><div>I have no idea how to approach that in a spec.</div><div>I don't think I 'compare' with "existing implicit expansion", that might even be off-topic.</div><div><br></div><div>In reality, my DIP doesn't perform an 'expansion' in the terms that D might currently talk about tuple expansion. All my DIP does is to apply a transformation to a tuple. Tuple-in, tuple-out; that's not really an 'expansion' in current language terms, it's just a map transformation on the tuple itself.</div><div>I don't know how to fix this language.</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 mechanisms to implement them in D are awkward..." they are the <br>
standard functional approach. The DIP should at best refrain from making <br>
subjective evaluation. The high compile-time cost is good rationale.<br></blockquote><div><br></div><div>I find the awkwardness to be similarly motivating as the high compile-time cost. If the CT cost is prohibitive to my program and there is no reasonable workaround, a solution like this becomes necessary, but in other cases even where there is not a high compile-time cost, I care about the awkwardness and how ugly the code is to read and write; bloaty syntax and logical indirections via shim templates often written elsewhere that I have to go and find. It's often a volume of text that overwhelms surrounding code and allows the actual point to be lost.</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 proposal does not mention things like Reverse, Sort etc., which <br>
would need non-forward iteration to work efficiently and are not helped <br>
by the proposal.<br></blockquote><div><br></div><div>I don't understand the relevance of this point... can you show where iteration and tuples have overlapping semantics?</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">
* "often reaching quadratic complexity for relatively simple operations" <br>
-> a couple of (references to) examples would be great<br></blockquote><div><br></div><div>I mean, `staticMap` is the poster child, and it's the least offensive example possible to write ;)</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">
* "...expression to perform explicit tuple expansions at the expression <br>
level, which can express..." good candidate for rephrasing<br></blockquote><div><br></div><div>Yeah, the point made by Mr 'Q' below needs to feed into this... and I don't know how to do it.</div><div>It's not strictly an 'expression'... although it kind-of is.</div><div><br></div><div>I don't know spec language to deal with these syntax trees where they are not yet known to be expressions, or types, or... whatever.</div><div>The transformation (and tuples in general) exist as a point in compilation where value/type concepts are not yet relevant. They become relevant when evaluating the code that the tuple is plugged into at a later phase.</div><div>What do you call pre-determined syntax trees? What is the language to perform operations on a yet-to-be-determined 'kind' of thing?</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">
* "a unary ... syntax" -> "s a unary ... postfix operator"<br></blockquote><div><br></div><div>Yes.</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">
* "(Tup*10)...  -->  ( Tup[0]*10, Tup[1]*10, Tup[2]*10 )" -> the example <br>
does not clarify how one expression expands into multiple expressions; <br>
this is not something that an operator does. The parens don't help - are <br>
they required, provided for illustration...? The meaning of the <br>
expansion (e.g. array initialization vs. function call etc) is <br>
determined by the context of the expansion. That's why the C++ proposal <br>
and standard focus most of the description on expansion loci.<br></blockquote><div><br></div><div>Actually, the parens are a bug in the DIP. It should read:</div><div>  (Tup*10)...  -->  (Tup[0]*10), (Tup[1]*10), (Tup[2]*10)<br></div><div><br></div><div>I thought that should be clear. And yes, the parens are necessary because I use a bin-op in this example which have lower precedence than unary operators.</div><div><br></div><div>Should I write:</div><div>  

(Tup*10)...  -->  AliasSeq!((Tup[0]*10), (Tup[1]*10), (Tup[2]*10 ))</div><div><br></div><div>I'm not sure using `AliasSeq`, which is a piece of library, is appropriate in a spec?</div><div><br></div><div>Again, I try to show semantic through obvious example here because the spec language I refer to above is mysterious to me.</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">
* "C++11 implemented template parameter pack expansion with similar <br>
semantics, and it has been a great success in the language. Coupled with <br>
D's superior metaprogramming feature set, D users can gain even greater <br>
value from this novel feature." -> specious argument, even if we allow <br>
for the "great success" in C++. (Most uses of "..." in C++ are sheer <br>
black magic and have required simplifications in C++17. NOT a success <br>
story.) The main problem is different though. C++ parameter packs don't <br>
enjoy /any/ other operation aside from expansion and "...".</blockquote><div><br></div><div><div>Well... what do you want? Should I just remove that? People asked me to add it.</div><div></div></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">To add that <br>
to the many existing operators for tuples that D has and claim it'll <br>
just work great because it did in C++ does not stand to reason.<br></blockquote><div><br></div><div>What operators do tuples have in D? We can slice and index them... I think that's all?</div><div>Why might you imagine this DIP would interact with tuple element indexing? Why is that significant enough to call out explicitly?</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">
* Major bug: the "Rationale" discusses only expression, whereas <br>
staticMap does not use expressions. It just processes tuples, which may <br>
contain types. Types cannot appear in expressions. C++ goes to great <br>
lengths to distinguish between template parameter packs (which may be <br>
one of type parameter pack, value parameter pack, and template template <br>
parameter pack) and function parameter packs (which may only be <br>
parameter declarations). By the Rationale nothing except expressions <br>
will be accessible to D's proposed "...". That means no staticMap for <br>
non-valies (e.g. staticMap!(Unqual, types)), which probably wasn't the <br>
intent of the DIP.<br></blockquote><div><br></div><div>Yes, as mentioned above, and also by Q below, this is the critical issue with this DIP, and I have no idea how to address this.</div><div>Everywhere I use the term 'expression' is invalid, but what do I write instead?</div><div><br></div><div>`syntax...` <- what is 'syntax' called in spec-language? It could be any syntax tree that makes grammatical sense.</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 implementation will explore expr" -> there's no formal definition <br>
of "explore". The C++ spec mentions "the largest expression to the left <br>
of the ...". Probably that would work here, too.<br></blockquote><div><br></div><div>Also an important point... how do you imagine that phrase you reference applying here? Can you suggest a better sentence?</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">
* "A second form shall exist which may implement a static reduce <br>
operation with the syntax expr [BinOp] ..." What happens if the tuple is <br>
empty?</blockquote><div><br></div><div>Compile error on empty tuple. I thought that was stated in the DIP, but I missed it. It states the rules on equal length, and no tuple present, but misses empty tuple >_<</div><div></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">C++17 allows ... only in between operators, e.g.:<br>
<br>
return false || ... || args == value;</blockquote><div><br></div><div>I haven't specified this, because I don't believe it's necessary the same way it is in C++. This is necessary in C++ because parameter packs are barely part of the language, and painfully cumbersome to interact with. In D, if you want a limit value, I think it would be reasonable to just append a limit value to the tuple in-situ.</div><div>There has been a lot of discussion about first-class tuples in D, and in that future you'd be able to do `MyTup ~ limit`, but for now `AliasSeq!(MyTup, limit)` seems convenient enough to me that it shouldn't require that we spec a limit syntax like C++.</div><div>If it's determined in the future that we want the limit case, it can be trivially added with a follow-up DIP, but I would not add it eagerly, I believe it's unnecessary.</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">
thus allowing the author to choose the limit value.<br>
<br>
* The "Compliation Performance" needs to discuss how the operator <br>
handles backward iteration.<br></blockquote><div><br></div><div>I don't understand what you're asking about here? Tuples don't 'iterate'... I'm not aware my DIP impacts or intersects any semantics dealing with iteration that should need to be called out?</div><div><br></div><div>...</div><div><br></div><div>These are all good points. Are you opposed to this DIP? If not, would you consider collaborating on this?</div><div>I don't really know appropriate language to address some of your points. I'm convinced the DIP will fail on account of the points you make, and if I can't correct them, then it's an automatic fail, and I might as well withdraw it now to save myself the torture, and you the time destroying it in a few weeks.</div><div><br></div><div>Or anyone else...? This definitely needs fixing, and I don't really know how to do it.</div></div></div>