www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Discussion Thread: DIP 1037--Add Unary Operator ...--Community Review

reply Mike Parker <aldacron gmail.com> writes:
This is the discussion thread for the first round of Community 
Review of DIP 1037, "Add Unary Operator ...":

https://github.com/dlang/DIPs/blob/ba81eec84ddf0aeeb2cb652743b292455ec8c62a/DIPs/DIP1037.md

The review period will end at 11:59 PM ET on November 10, or when 
I make a post declaring it complete. Discussion in this thread 
may continue beyond that point.

Here in the discussion thread, you are free to discuss anything 
and everything related to the DIP. Express your support or 
opposition, debate alternatives, argue the merits, etc.

However, if you have any specific feedback on how to improve the 
proposal itself, then please post it in the feedback thread. The 
feedback thread will be the source for the review summary that I 
will write at the end of this review round. I will post a link to 
that thread immediately following this post. Just be sure to read 
and understand the Reviewer Guidelines before posting there:

https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

And my blog post on the difference between the Discussion and 
Feedback threads:

https://dlang.org/blog/2020/01/26/dip-reviews-discussion-vs-feedback/

Please stay on topic here. I will delete posts that are 
completely off-topic.
Oct 27 2020
next sibling parent Mike Parker <aldacron gmail.com> writes:
On Tuesday, 27 October 2020 at 10:54:07 UTC, Mike Parker wrote:
 However, if you have any specific feedback on how to improve 
 the proposal itself, then please post it in the feedback 
 thread. The feedback thread will be the source for the review 
 summary that I will write at the end of this review round. I 
 will post a link to that thread immediately following this post.
The feedback thread is here: https://forum.dlang.org/post/rihufokcywwlityflfco forum.dlang.org
Oct 27 2020
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On Tuesday, 27 October 2020 at 10:54:07 UTC, Mike Parker wrote:
 This is the discussion thread for the first round of Community 
 Review of DIP 1037, "Add Unary Operator ...":

 https://github.com/dlang/DIPs/blob/ba81eec84ddf0aeeb2cb652743b292455ec8c62a/DIPs/DIP1037.md
Is there a risk of causing some form of ambiguity with variadic functions? For example: void a(int[] a ...); void b(int[]...); void c(int...); alias A = AliasSeq!(int); void d(A...); I didn't know `c` was legal, but apparently it is (and therefor `d` as well). -- /Jacob Carlborg
Oct 28 2020
next sibling parent Manu <turkeyman gmail.com> writes:
On Wed, Oct 28, 2020 at 9:05 PM Jacob Carlborg via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Tuesday, 27 October 2020 at 10:54:07 UTC, Mike Parker wrote:
 This is the discussion thread for the first round of Community
 Review of DIP 1037, "Add Unary Operator ...":
https://github.com/dlang/DIPs/blob/ba81eec84ddf0aeeb2cb652743b292455ec8c62a/DIPs/DIP1037.md Is there a risk of causing some form of ambiguity with variadic functions? For example: void a(int[] a ...); void b(int[]...); void c(int...); alias A = AliasSeq!(int); void d(A...); I didn't know `c` was legal, but apparently it is (and therefor `d` as well).
What does `c` mean? Is it possible that c and d are identical things here, even with my DIP in place?
Oct 28 2020
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
Your example `void c(int...)` mangles as `void c(int)`, and it's also
callable only with a single int arg.
Under my DIP, `d` as you show will perform an identity map, which yields
`void d(int)`, so the result is identical.
I explored for ambiguities to the extent of my imagination but I didn't
find any. The is() expression was where I was most concerned about
ambiguities.

On Wed, Oct 28, 2020 at 9:44 PM Manu <turkeyman gmail.com> wrote:

 On Wed, Oct 28, 2020 at 9:05 PM Jacob Carlborg via Digitalmars-d <
 digitalmars-d puremagic.com> wrote:

 On Tuesday, 27 October 2020 at 10:54:07 UTC, Mike Parker wrote:
 This is the discussion thread for the first round of Community
 Review of DIP 1037, "Add Unary Operator ...":
https://github.com/dlang/DIPs/blob/ba81eec84ddf0aeeb2cb652743b292455ec8c62a/DIPs/DIP1037.md Is there a risk of causing some form of ambiguity with variadic functions? For example: void a(int[] a ...); void b(int[]...); void c(int...); alias A = AliasSeq!(int); void d(A...); I didn't know `c` was legal, but apparently it is (and therefor `d` as well).
What does `c` mean? Is it possible that c and d are identical things here, even with my DIP in place?
Oct 28 2020
prev sibling parent reply Q. Schroll <qs.il.paperinik gmail.com> writes:
On Wednesday, 28 October 2020 at 10:57:37 UTC, Jacob Carlborg 
wrote:
 On Tuesday, 27 October 2020 at 10:54:07 UTC, Mike Parker wrote:
 This is the discussion thread for the first round of Community 
 Review of DIP 1037, "Add Unary Operator ...":

 https://github.com/dlang/DIPs/blob/ba81eec84ddf0aeeb2cb652743b292455ec8c62a/DIPs/DIP1037.md
Is there a risk of causing some form of ambiguity with variadic functions?
No, because the DIP does not propose anything with types. In the DIP, it says "expression" everywhere; it's for use in expressions, not types. It doesn't forbid types to occur in the tuple for good reasons, simply because types can very well occur in expression contexts, but the result will always be an expression. If you want a drastic example how far reaching expression vs type context is: given a type T, T[] can mean: slice of T or T.opIndex. If T defines static opIndex, in an expression context, T[] will mean T.opIndex, and in a type context, it will mean slice of T (kinda obvious). Let Ts := (T1, T2); if you'd do (Ts[]).sizeof... --- because ... is only valid in an expression context --- it *must* lower to (T1.opIndex.sizeof, T2.opIndex.sizeof). By the grammar given in the DIP, the ... do not have anything to do with the type expression stuff. The example given in the DIP with `cast(Types)Values...` might work by accident because types are also expressions. By the grammar provided, `cast(Types[])Values...` could never work as intended! The example alias staticMap(alias F, T...) = F!T...; cannot work. By the grammar provided, F!T... must be an expression, not a "type expression", but alias requires a type context as its target. (I.e. alias x = 5; doesn't work; alias x = y + 1; doesn't work either because the right-hand sides aren't types.) In the Feedback Thread, I commented that it would be great to have the proposed operator apply to type contexts as well [1]. Didn't get an answer, but do hope I get one eventually. Problem is, as you started digging: For a class C (and classes only, not structs or anything else), the parameter definition C... is already defined [2, see "4. For class objects"]. For example, class C { this(int, string) { } } void foo(C...) { } void main() { foo(1, "abc"); } compiles [3]. So if C is the last entry in a type-only AliasSeq that is used in a parameter list, notations clash. Currently valid [4] code like import std.meta : AliasSeq; class C { this(int, string) { } } alias Types = AliasSeq!(int, string, C); void foo(Types args...) { } void main() { foo(1, "abc", 2, "xyz"); } would no longer compile, since `Types...` would be the literal same as using `Types` without dots. [1] https://forum.dlang.org/post/fogbdhcdeukiucbxxxns forum.dlang.org [2] https://dlang.org/spec/function.html#typesafe_variadic_functions [3] https://run.dlang.io/is/GmgAaG [4] https://run.dlang.io/is/DeGZF7
Nov 02 2020
parent reply Manu <turkeyman gmail.com> writes:
On Tue, Nov 3, 2020 at 8:55 AM Q. Schroll via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Wednesday, 28 October 2020 at 10:57:37 UTC, Jacob Carlborg
 wrote:
 On Tuesday, 27 October 2020 at 10:54:07 UTC, Mike Parker wrote:
 This is the discussion thread for the first round of Community
 Review of DIP 1037, "Add Unary Operator ...":
https://github.com/dlang/DIPs/blob/ba81eec84ddf0aeeb2cb652743b292455ec8c62a/DIPs/DIP1037.md
 Is there a risk of causing some form of ambiguity with variadic
 functions?
No, because the DIP does not propose anything with types. In the DIP, it says "expression" everywhere; it's for use in expressions, not types. It doesn't forbid types to occur in the tuple for good reasons, simply because types can very well occur in expression contexts, but the result will always be an expression. If you want a drastic example how far reaching expression vs type context is: given a type T, T[] can mean: slice of T or T.opIndex. If T defines static opIndex, in an expression context, T[] will mean T.opIndex, and in a type context, it will mean slice of T (kinda obvious). Let Ts := (T1, T2); if you'd do (Ts[]).sizeof... --- because ... is only valid in an expression context --- it *must* lower to (T1.opIndex.sizeof, T2.opIndex.sizeof). By the grammar given in the DIP, the ... do not have anything to do with the type expression stuff. The example given in the DIP with `cast(Types)Values...` might work by accident because types are also expressions. By the grammar provided, `cast(Types[])Values...` could never work as intended! The example alias staticMap(alias F, T...) = F!T...; cannot work. By the grammar provided, F!T... must be an expression, not a "type expression", but alias requires a type context as its target. (I.e. alias x = 5; doesn't work; alias x = y + 1; doesn't work either because the right-hand sides aren't types.) In the Feedback Thread, I commented that it would be great to have the proposed operator apply to type contexts as well [1]. Didn't get an answer, but do hope I get one eventually. Problem is, as you started digging: For a class C (and classes only, not structs or anything else), the parameter definition C... is already defined [2, see "4. For class objects"]. For example, class C { this(int, string) { } } void foo(C...) { } void main() { foo(1, "abc"); } compiles [3]. So if C is the last entry in a type-only AliasSeq that is used in a parameter list, notations clash. Currently valid [4] code like import std.meta : AliasSeq; class C { this(int, string) { } } alias Types = AliasSeq!(int, string, C); void foo(Types args...) { } void main() { foo(1, "abc", 2, "xyz"); } would no longer compile, since `Types...` would be the literal same as using `Types` without dots. [1] https://forum.dlang.org/post/fogbdhcdeukiucbxxxns forum.dlang.org [2] https://dlang.org/spec/function.html#typesafe_variadic_functions [3] https://run.dlang.io/is/GmgAaG [4] https://run.dlang.io/is/DeGZF7
Thank you for this analysis. This is useful. I'll confirm the DIP's spec and implementation against your points. It might be that the implementation works by happen-stance, or perhaps my stated grammar change wasn't accurate. It's very hard to express a grammar change in a DIP like this, since D doesn't have a grammar as such; it's just an implementation, and reverse-engineering a grammar from the implementation is imprecise. Perhaps my implementation implies additional grammar changes that I didn't notice.
Nov 02 2020
next sibling parent reply Q. Schroll <qs.il.paperinik gmail.com> writes:
On Tuesday, 3 November 2020 at 02:30:58 UTC, Manu wrote:
 Perhaps my implementation implies additional grammar changes 
 that I didn't notice.
It does, if it should work on types. In the easiest case, if you want alias X(Args...) = (T!Args)...; to work like alias X(Args...) = staticMap!(T, Args); you cannot do that by merely adding a new PostfixExpression. It is necessary to add `...` to BasicType2X, i.e. BasicType2X: * [ ] [ AssignExpression ] [ AssignExpression .. AssignExpression ] + ... [ Type ] but I may have overlooked something and it might not suffice. The grammar concerning "type expressions" is convoluted and has some stuff going on in AltDeclarator where I'm not entirely sure it can be ignored.
Nov 02 2020
parent reply Manu <turkeyman gmail.com> writes:
On Tue, Nov 3, 2020 at 1:15 PM Q. Schroll via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Tuesday, 3 November 2020 at 02:30:58 UTC, Manu wrote:
 Perhaps my implementation implies additional grammar changes
 that I didn't notice.
It does, if it should work on types. In the easiest case, if you want alias X(Args...) = (T!Args)...; to work like alias X(Args...) = staticMap!(T, Args); you cannot do that by merely adding a new PostfixExpression. It is necessary to add `...` to BasicType2X, i.e. BasicType2X: * [ ] [ AssignExpression ] [ AssignExpression .. AssignExpression ] + ... [ Type ] but I may have overlooked something and it might not suffice. The grammar concerning "type expressions" is convoluted and has some stuff going on in AltDeclarator where I'm not entirely sure it can be ignored.
You're right, and a change like that does exist in my implementation somewhere; I just need to look again at the implementation to spot it and confirm it in the grammar changes. I wondered if I overlooked some cases too; but the unit tests are fairly comprehensive and exercise all the constructs that we ever imagined could be useful. There's a grammar change that supports: alias staticMap(F, Args...) = F!Args...; And also: MyTemplate!(expr...) <-- appearance in template parameter lists It's also deliberate and necessary that the grammar is NOT modified such that `...` could be accepted in argument list definitions, because that's where ambiguity can occur. If you want to use `...` in an argument list, you can make an alias on the preceding line: alias MappedArgs = TupExpr...; void fun(MappedArgs args) { ... } <-- `...` can not appear in a parameter list, so hoist it to the line above I actually really like this incidental restriction; it makes declarations clearer.
Nov 02 2020
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/3/20 2:05 AM, Manu wrote:
    MyTemplate!(expr...) <-- appearance in template parameter lists
By the way in C++ the expansion applies to so-called patterns, not expressions: pattern... The pattern allowed depends on the context in which it's seen. E.g., if it's in a function call arguments, it's the largest expression to the left of "...". The difficulty in D is that it's not always clear if something is meant to be an expression or a type. Consider: template X(T...) { } X!(pattern...); It's unclear whether the pattern is meant to expand into types or expressions. I don't know whether there's a case in D where that could create a confusion.
Nov 03 2020
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 3 November 2020 at 13:46:20 UTC, Andrei Alexandrescu 
wrote:
 On 11/3/20 2:05 AM, Manu wrote:
    MyTemplate!(expr...) <-- appearance in template parameter 
 lists
By the way in C++ the expansion applies to so-called patterns, not expressions: pattern... The pattern allowed depends on the context in which it's seen. E.g., if it's in a function call arguments, it's the largest expression to the left of "...". The difficulty in D is that it's not always clear if something is meant to be an expression or a type. Consider: template X(T...) { } X!(pattern...); It's unclear whether the pattern is meant to expand into types or expressions. I don't know whether there's a case in D where that could create a confusion.
A Type in practice is just an expression. Consider: alias A(T) = T; pragma(msg, A!int); // prints int; pragma(msg, !A!int); // prints false. If you can use ! on something, it's an expression.
Nov 03 2020
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 3 November 2020 at 16:34:39 UTC, Stefan Koch wrote:
 A Type in practice is just an expression.

 Consider:

 alias A(T) = T;
Is it though? It would be nice if alias could bind to expressions, but it clearly can't. alias T = 42; // fails enum __tmp = 42; alias T = __tmp; // ok
Nov 03 2020
parent Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 3 November 2020 at 17:23:23 UTC, Ola Fosheim Grøstad 
wrote:
 On Tuesday, 3 November 2020 at 16:34:39 UTC, Stefan Koch wrote:
 A Type in practice is just an expression.

 Consider:

 alias A(T) = T;
Is it though? It would be nice if alias could bind to expressions, but it clearly can't. alias T = 42; // fails enum __tmp = 42; alias T = __tmp; // ok
I said all types are expressions. (Even though the language does not admit it yet.) Not all expressions are types.
Nov 04 2020
prev sibling parent reply Q. Schroll <qs.il.paperinik gmail.com> writes:
On Tuesday, 3 November 2020 at 07:05:19 UTC, Manu wrote:
 There's a grammar change that supports:
    alias staticMap(F, Args...) = F!Args...;
 And also:
   MyTemplate!(expr...) <-- appearance in template parameter 
 lists

 It's also deliberate and necessary that the grammar is NOT 
 modified such
 that `...` could be accepted in argument list definitions, [...]
 I actually really like this incidental restriction; it makes 
 declarations clearer.
I really don't think that such a special case is necessary. Maybe one way to litigate this is to (using terms just learned from Andrei) require the pattern to be in parentheses. Since `identifier...` (where identifier is a tuple) is the same as `identifier` per se, one could solve the question how long the `...` expands to the right by requiring parentheses. No one ever asked how far template arguments are read, i.e. whether T!Arg[0] means (T!Arg)[0] or T!(Arg[0]) because it is single token or you need parentheses. Not even T![0,1,2] (an array literal) compiles! So... maybe it is (pattern)... that is The Right Thing™? That way, you can have it in function parameter lists: void func((pattern)... args) { .. } An example would be void func(Ts...)((Ts[])... args) { .. } for a function template taking any kinds of slices. It is unambiguous because the parentheses aren't legal in current state of D. Notice that `const(Ts)...` is still the old syntax, i.e. the `...` are for type-safe variadic parameters. Full example: https://run.dlang.io/is/3QvFCA Since there are types like int* that can be expressed with a token sequence that aren't legal as expressions, there is a need for type patterns and expression patterns; or patterns in general must accommodate types and expressions together.
Nov 04 2020
parent Manu <turkeyman gmail.com> writes:
On Thu, Nov 5, 2020 at 2:45 PM Q. Schroll via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Tuesday, 3 November 2020 at 07:05:19 UTC, Manu wrote:
 There's a grammar change that supports:
    alias staticMap(F, Args...) =3D F!Args...;
 And also:
   MyTemplate!(expr...) <-- appearance in template parameter
 lists

 It's also deliberate and necessary that the grammar is NOT
 modified such
 that `...` could be accepted in argument list definitions, [...]
 I actually really like this incidental restriction; it makes
 declarations clearer.
I really don't think that such a special case is necessary. Maybe one way to litigate this is to (using terms just learned from Andrei) require the pattern to be in parentheses. Since `identifier...` (where identifier is a tuple) is the same as `identifier` per se, one could solve the question how long the `...` expands to the right by requiring parentheses. No one ever asked how far template arguments are read, i.e. whether T!Arg[0] means (T!Arg)[0] or T!(Arg[0]) because it is single token or you need parentheses. Not even T![0,1,2] (an array literal) compiles! So... maybe it is (pattern)... that is The Right Thing=E2=84=A2? That way, you can have it in function parameter lists: void func((pattern)... args) { .. } An example would be void func(Ts...)((Ts[])... args) { .. } for a function template taking any kinds of slices. It is unambiguous because the parentheses aren't legal in current state of D.
Good point. Except elipsis would be inside the parens. That is absolutely possible, and it might even already just happen to work because how the grammar is naturally. Notice that `const(Ts)...` is still the old syntax, i.e. the
 `...` are for type-safe variadic parameters. Full example:
 https://run.dlang.io/is/3QvFCA

 Since there are types like int* that can be expressed with a
 token sequence that aren't legal as expressions, there is a need
 for type patterns and expression patterns; or patterns in general
 must accommodate types and expressions together.
Nov 05 2020
prev sibling next sibling parent Q. Schroll <qs.il.paperinik gmail.com> writes:
On Tuesday, 3 November 2020 at 02:30:58 UTC, Manu wrote:
 It might be that the implementation works by happen-stance, or 
 perhaps my
 stated grammar change wasn't accurate.
Probably you didn't care that much about the formal grammar and wanted to get the implementation done. To be honest, I thought about writing a similar DIP, but chickened out because the "pushing down" of the expansion looked complicated to me. If that gets accepted (after the rough edges got rounded), it will make static indexing even more wanting.
Nov 02 2020
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/2/20 9:30 PM, Manu wrote:
 It's very hard to express a grammar change in a DIP like this, since D 
 doesn't have a grammar as such; it's just an implementation, and 
 reverse-engineering a grammar from the implementation is imprecise. 
 Perhaps my implementation implies additional grammar changes that I 
 didn't notice.
I thought the grammar is fairly complete, no? It's the semantics that's poorly defined.
Nov 02 2020
parent Manu <turkeyman gmail.com> writes:
On Tue, Nov 3, 2020 at 4:05 PM Andrei Alexandrescu via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On 11/2/20 9:30 PM, Manu wrote:
 It's very hard to express a grammar change in a DIP like this, since D
 doesn't have a grammar as such; it's just an implementation, and
 reverse-engineering a grammar from the implementation is imprecise.
 Perhaps my implementation implies additional grammar changes that I
 didn't notice.
I thought the grammar is fairly complete, no? It's the semantics that's poorly defined.
It may be complete, but it's difficult to relate to the code, and when making changes to DMD, it's easy to make changes and not clearly see how it might have affected the grammar shown in the spec. It's just that someone reverse-engineered an approx grammar from the implementation. DMD doesn't have a formal grammar; it's implementation defined.
Nov 02 2020
prev sibling next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 27 October 2020 at 10:54:07 UTC, Mike Parker wrote:
 This is the discussion thread for the first round of Community 
 Review of DIP 1037, "Add Unary Operator ...":
I think it should be made more generic and flexible. Make it work with all sequence types that provides a length and indexing. Make it possible to offset. Make it work for empty sequences (initial value for fold/reduce). Make the comma-expansion more intuitive. E.g. (pseduo): Given: seq1 = /* 1 ,2, 3 */ seq2 = /* 10, 20, 30, 40, 50*/ IN: (seq1[_]*10 + seq2[_+1], ...) OUT (e.g. length = min(seq1.length, seq2.length): (seq1[0]*10 + seq2[1], seq1[1]*10 + seq2[2], seq1[2]*10 + seq2[3])
Oct 28 2020
parent reply Manu <turkeyman gmail.com> writes:
On Wed, Oct 28, 2020 at 11:35 PM Ola Fosheim Gr=C3=B8stad via Digitalmars-d=
 <
digitalmars-d puremagic.com> wrote:

 On Tuesday, 27 October 2020 at 10:54:07 UTC, Mike Parker wrote:
 This is the discussion thread for the first round of Community
 Review of DIP 1037, "Add Unary Operator ...":
I think it should be made more generic and flexible. Make it work with all sequence types that provides a length and indexing.
Definitely not my DIP. I can immediately imagine heaps of issues with that idea, and I have never wanted that before. If you want to do a non-static map, then use `map`, which accepts a lambda and looks and feels very natural and convenient. Make it possible to offset. Not sure what this means? You can slice tuples in D, does that not give you the ability to offset as you like? Make it work for empty sequences (initial
 value for fold/reduce).
I don't think this is necessary, and it is deliberately omitted. You can append a limit value to a tuple trivially using something like AliasSeq!(limit, MyTup). Perhaps in the future if we ever get first-class tuples, you can use `~` to intuitively concatenate tuples, and I think that's more proper than what C++ does. If it turns out I'm wrong and it should exist, then it's a trivial expansion. Make the comma-expansion more intuitive.
 E.g. (pseduo):

 Given:

 seq1 =3D /* 1 ,2, 3 */
 seq2 =3D /* 10, 20, 30, 40, 50*/


 IN:
 (seq1[_]*10 + seq2[_+1], ...)

 OUT (e.g. length =3D min(seq1.length, seq2.length):
 (seq1[0]*10 + seq2[1], seq1[1]*10 + seq2[2], seq1[2]*10 + seq2[3])
That looks like a minefield of grammatical issues. Why would you prefer that with the comma separating the expression and `...`?
Oct 28 2020
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 28 October 2020 at 14:48:48 UTC, Manu wrote:
 Definitely not my DIP. I can immediately imagine heaps of 
 issues with that
 idea, and I have never wanted that before.
 If you want to do a non-static map, then use `map`, which 
 accepts a lambda
 and looks and feels very natural and convenient.
Make the syntax uniform. Don't continue with special cases...
 Not sure what this means? You can slice tuples in D, does that 
 not give you the ability to offset as you like?
That was an example. Reverse. Every other etc.
 I don't think this is necessary, and it is deliberately omitted.
That is a serious omission. Fold needs an initial value in order to be generic.
 IN:
 (seq1[_]*10 + seq2[_+1], ...)

 OUT (e.g. length = min(seq1.length, seq2.length):
 (seq1[0]*10 + seq2[1], seq1[1]*10 + seq2[2], seq1[2]*10 + 
 seq2[3])
That looks like a minefield of grammatical issues.
No, it isn't. D uses a recursive descent parser and it will evaluate the first expression to an expression with a special token. Trivial extension of the parser.
 Why would you prefer that with the comma separating the 
 expression and `...`?
Because what you proposed is not intuitive: "(seq1)..." does not give any hint of it being expanded to a comma separated list. That is not good from a usability point of view (legibility).
Oct 28 2020
parent reply Paul Backus <snarwin gmail.com> writes:
On Wednesday, 28 October 2020 at 14:56:10 UTC, Ola Fosheim 
Grøstad wrote:
 I don't think this is necessary, and it is deliberately 
 omitted.
That is a serious omission. Fold needs an initial value in order to be generic.
You can add an initial value outside of the fold expression: false || Tup == 10 || ...
Oct 28 2020
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 28 October 2020 at 15:05:19 UTC, Paul Backus wrote:
 You can add an initial value outside of the fold expression:

     false || Tup == 10 || ...
Ok, but the problem is in generic code. You could adopt init as the initial value for fold, but it fails miserably for floats as they don't have 0 as the init, but NaN... Will it work with overloads so that the initial value can be a completely different type? (If you want to trap empty tuples, but have no unused value.)
Oct 28 2020
parent reply Paul Backus <snarwin gmail.com> writes:
On Wednesday, 28 October 2020 at 15:25:18 UTC, Ola Fosheim 
Grøstad wrote:
 On Wednesday, 28 October 2020 at 15:05:19 UTC, Paul Backus 
 wrote:
 You can add an initial value outside of the fold expression:

     false || Tup == 10 || ...
Ok, but the problem is in generic code. You could adopt init as the initial value for fold, but it fails miserably for floats as they don't have 0 as the init, but NaN... Will it work with overloads so that the initial value can be a completely different type? (If you want to trap empty tuples, but have no unused value.)
Generic code can deal with this the same way std.algorithm.reduce does: by taking the initial value as a parameter, or by requiring that the tuple be non-empty.
Oct 28 2020
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 28 October 2020 at 15:30:28 UTC, Paul Backus wrote:
 Generic code can deal with this the same way 
 std.algorithm.reduce does: by taking the initial value as a 
 parameter, or by requiring that the tuple be non-empty.
What I meant is what if the library author provided a function for "numbers", but never tested the code with floats. If the initial value is required then the library author would have remembered to set the initial value to "cast(T)0" for addition or "cast(T)1" for multiplication.
Oct 28 2020
parent reply Paul Backus <snarwin gmail.com> writes:
On Wednesday, 28 October 2020 at 15:43:24 UTC, Ola Fosheim 
Grøstad wrote:
 On Wednesday, 28 October 2020 at 15:30:28 UTC, Paul Backus 
 wrote:
 Generic code can deal with this the same way 
 std.algorithm.reduce does: by taking the initial value as a 
 parameter, or by requiring that the tuple be non-empty.
What I meant is what if the library author provided a function for "numbers", but never tested the code with floats. If the initial value is required then the library author would have remembered to set the initial value to "cast(T)0" for addition or "cast(T)1" for multiplication.
The library author could just as easily use `T.init` as the initial value, and if the code is never tested with floats, it will appear to work just fine. So requiring an initial value does nothing to prevent this hypothetical bug.
Oct 28 2020
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 28 October 2020 at 17:48:21 UTC, Paul Backus wrote:
 The library author could just as easily use `T.init` as the 
 initial value, and if the code is never tested with floats, it 
 will appear to work just fine. So requiring an initial value 
 does nothing to prevent this hypothetical bug.
No, it is common to fold with 0 for addition and 1 for multiplication. Anyone that has some programming background will use that when the think about initial value. Or "zero" and "identity", which in my view should be traits for numbers. In my own lib for generic programming I use those. Then you can write generic code that work for matrices etc.
Oct 28 2020
parent reply Paul Backus <snarwin gmail.com> writes:
On Wednesday, 28 October 2020 at 17:52:41 UTC, Ola Fosheim 
Grøstad wrote:
 On Wednesday, 28 October 2020 at 17:48:21 UTC, Paul Backus 
 wrote:
 The library author could just as easily use `T.init` as the 
 initial value, and if the code is never tested with floats, it 
 will appear to work just fine. So requiring an initial value 
 does nothing to prevent this hypothetical bug.
No, it is common to fold with 0 for addition and 1 for multiplication. Anyone that has some programming background will use that when the think about initial value.
The bug you described in your previous post can only ever occur if the programmer uses an incorrect initial value, not if he or she forgets to include an initial value. If you are willing to assume that the programmer will not use an incorrect initial value, then the bug you are (supposedly) worried about will never occur in the first place.
Oct 28 2020
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 28 October 2020 at 18:00:15 UTC, Paul Backus wrote:
 The bug you described in your previous post can only ever occur 
 if the programmer uses an incorrect initial value, not if he or 
 she forgets to include an initial value. If you are willing to 
 assume that the programmer will not use an incorrect initial 
 value, then the bug you are (supposedly) worried about will 
 never occur in the first place.
No, the bug I described is when you take an empty tuple. What will the value be when nobody provided an initial value? Say, for a matrix.
Oct 28 2020
prev sibling next sibling parent reply Guillaume Piolat <first.name gmail.com> writes:
On Tuesday, 27 October 2020 at 10:54:07 UTC, Mike Parker wrote:
 
 Here in the discussion thread, you are free to discuss anything 
 and everything related to the DIP. Express your support or 
 opposition, debate alternatives, argue the merits, etc.
The DIP brings compile-time improvements, but this is a feature relatively reserved for the standard library so perhaps the blocker is that is also has an easy syntax; Being an operator it brings many new questions such as precedence, syntax compatibility, whereas if it was a compiler intrinsic like __mapTuple (very bad name) the quantity of debate would be less perhaps? Possibly it could remain "niche" and with loud syntax and we would still gain the compile-time improvements.
Oct 28 2020
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Wednesday, 28 October 2020 at 22:42:16 UTC, Guillaume Piolat 
wrote:
 On Tuesday, 27 October 2020 at 10:54:07 UTC, Mike Parker wrote:
 
 Here in the discussion thread, you are free to discuss 
 anything and everything related to the DIP. Express your 
 support or opposition, debate alternatives, argue the merits, 
 etc.
The DIP brings compile-time improvements, but this is a feature relatively reserved for the standard library so perhaps the blocker is that is also has an easy syntax; Being an operator it brings many new questions such as precedence, syntax compatibility, whereas if it was a compiler intrinsic like __mapTuple (very bad name) the quantity of debate would be less perhaps? Possibly it could remain "niche" and with loud syntax and we would still gain the compile-time improvements.
As is amply evident from the history of __traits, making something ugly on purpose will not stop people from using it, it will just cause needless aggravation for them when they do. If this is worth doing, it's worth doing right.
Oct 28 2020
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Oct 28, 2020 at 11:39:08PM +0000, Paul Backus via Digitalmars-d wrote:
 On Wednesday, 28 October 2020 at 22:42:16 UTC, Guillaume Piolat wrote:
[...]
 The DIP brings compile-time improvements, but this is a feature
 relatively reserved for the standard library so perhaps the blocker
 is that is also has an easy syntax;
[...]
 As is amply evident from the history of __traits, making something
 ugly on purpose will not stop people from using it, it will just cause
 needless aggravation for them when they do.
 
 If this is worth doing, it's worth doing right.
+1. I think it's a mistake to differentiate between "user code" and "standard library code"; IMO properly-designed code generally should be >95% library and <5% driver-specific code. Meaning that if a feature is useful for the standard library, then it's useful for user code, and should be designed with that in mind. T -- Don't drink and derive. Alcohol and algebra don't mix.
Oct 28 2020
prev sibling parent Manu <turkeyman gmail.com> writes:
On Thu, Oct 29, 2020 at 8:45 AM Guillaume Piolat via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Tuesday, 27 October 2020 at 10:54:07 UTC, Mike Parker wrote:
 Here in the discussion thread, you are free to discuss anything
 and everything related to the DIP. Express your support or
 opposition, debate alternatives, argue the merits, etc.
The DIP brings compile-time improvements, but this is a feature relatively reserved for the standard library so perhaps the blocker is that is also has an easy syntax; Being an operator it brings many new questions such as precedence, syntax compatibility, whereas if it was a compiler intrinsic like __mapTuple (very bad name) the quantity of debate would be less perhaps? Possibly it could remain "niche" and with loud syntax and we would still gain the compile-time improvements.
I'm not sure what you mean it's reserved for the standard library? That is definitely not the case. This is intended to be used by users who want to write good code.
Oct 28 2020
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
 From the Feedback Thread:

 * Major bug: the "Rationale" discusses only expression, whereas
 staticMap does not use expressions. It just processes tuples, which may
 contain types. Types cannot appear in expressions. C++ goes to great
 lengths to distinguish between template parameter packs (which may be
 one of type parameter pack, value parameter pack, and template template
 parameter pack) and function parameter packs (which may only be
 parameter declarations). By the Rationale nothing except expressions
 will be accessible to D's proposed "...". That means no staticMap for
 non-valies (e.g. staticMap!(Unqual, types)), which probably wasn't the
 intent of the DIP.
I am confused by this. Isn't it fine to work with expressions only? I mean staticMap's implementation can be replaced with a ... expansion, because even though there might be types in the list, there are no types in staticMap, just tuples. And a type can appear in an expression, as a template parameter: alias everyOther = AliasSeq!(0, 2, 4); alias everyOtherType = (AliasSeq!(int, uint, char, byte, ubyte, int)[everyOther])...; I think the DIP is intending for staticMap to be wholesale replaced with this, and seems to be saying this to me. I don't understand the above complaint, and why static map wouldn't work with types. Perhaps it's simply vocabulary that is the problem? -Steve
Oct 29 2020
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.com> writes:
On 10/29/20 9:48 AM, Steven Schveighoffer wrote:
  From the Feedback Thread:
 
 * Major bug: the "Rationale" discusses only expression, whereas
 staticMap does not use expressions. It just processes tuples, which may
 contain types. Types cannot appear in expressions. C++ goes to great
 lengths to distinguish between template parameter packs (which may be
 one of type parameter pack, value parameter pack, and template template
 parameter pack) and function parameter packs (which may only be
 parameter declarations). By the Rationale nothing except expressions
 will be accessible to D's proposed "...". That means no staticMap for
 non-valies (e.g. staticMap!(Unqual, types)), which probably wasn't the
 intent of the DIP.
I am confused by this. Isn't it fine to work with expressions only? I mean staticMap's implementation can be replaced with a ... expansion, because even though there might be types in the list, there are no types in staticMap, just tuples.
I don't think it works that way, no.
 And a type can appear in an expression, as a template parameter:
 
 alias everyOther = AliasSeq!(0, 2, 4);
 
 alias everyOtherType = (AliasSeq!(int, uint, char, byte, ubyte, 
 int)[everyOther])...;
 
 I think the DIP is intending for staticMap to be wholesale replaced with 
 this, and seems to be saying this to me. I don't understand the above 
 complaint, and why static map wouldn't work with types.
What would the implementation of staticMap with the DIP look like? As far as I can tell from the DIP it cannot be done.
 Perhaps it's simply vocabulary that is the problem?
May as well. The way the DIP is written, there's no discussion of tuples containing anything else but values.
Oct 30 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/30/20 2:29 PM, Andrei Alexandrescu wrote:
 On 10/29/20 9:48 AM, Steven Schveighoffer wrote:
 And a type can appear in an expression, as a template parameter:

 alias everyOther = AliasSeq!(0, 2, 4);

 alias everyOtherType = (AliasSeq!(int, uint, char, byte, ubyte, 
 int)[everyOther])...;

 I think the DIP is intending for staticMap to be wholesale replaced 
 with this, and seems to be saying this to me. I don't understand the 
 above complaint, and why static map wouldn't work with types.
What would the implementation of staticMap with the DIP look like? As far as I can tell from the DIP it cannot be done.
It has the implementation right in the DIP: alias staticMap(alias F, T...) = F!T...;
 Perhaps it's simply vocabulary that is the problem?
May as well. The way the DIP is written, there's no discussion of tuples containing anything else but values.
In the examples there are. e.g.: alias Values = AliasSeq!(1, 2, 3); alias Types = AliasSeq!(int, short, float); pragma(msg, cast(Types)Values...);
 cast(int)1, cast(short)2, cast(float)3
Maybe it's not as clear with terminology. In some places it talks about tuples and their "elements", and in others, it talks about "values". I don't think it ever specifically talks about types in the description. -Steve
Oct 30 2020
parent reply Manu <turkeyman gmail.com> writes:
On Sat, Oct 31, 2020 at 9:10 AM Steven Schveighoffer via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On 10/30/20 2:29 PM, Andrei Alexandrescu wrote:
 On 10/29/20 9:48 AM, Steven Schveighoffer wrote:
 And a type can appear in an expression, as a template parameter:

 alias everyOther = AliasSeq!(0, 2, 4);

 alias everyOtherType = (AliasSeq!(int, uint, char, byte, ubyte,
 int)[everyOther])...;

 I think the DIP is intending for staticMap to be wholesale replaced
 with this, and seems to be saying this to me. I don't understand the
 above complaint, and why static map wouldn't work with types.
What would the implementation of staticMap with the DIP look like? As far as I can tell from the DIP it cannot be done.
It has the implementation right in the DIP: alias staticMap(alias F, T...) = F!T...;
 Perhaps it's simply vocabulary that is the problem?
May as well. The way the DIP is written, there's no discussion of tuples containing anything else but values.
In the examples there are. e.g.: alias Values = AliasSeq!(1, 2, 3); alias Types = AliasSeq!(int, short, float); pragma(msg, cast(Types)Values...); > cast(int)1, cast(short)2, cast(float)3 Maybe it's not as clear with terminology. In some places it talks about tuples and their "elements", and in others, it talks about "values". I don't think it ever specifically talks about types in the description. -Steve
I was about to raise both those examples you showed here. I show staticMap's implementation right there, and I also show types in tuples. The trouble as I see is that there's a spec language problem, where a tuple element is a 'kind of thing' that I don't know what to call that. It may be a value, or a type, or an alias, and in most cases, I don't refer to the contents of the tuple, just to the tuple itself. The kind of thing in the elements is largely irrelevant to this dip; it's a later phase in compilation where (as with any tuple in normal circumstances) the elements of the tuple are determined to have some meaning in context. I think people are hung up by my use of the word 'expression' to mean "some syntax tree" involving whatever kind of thing that may be in the tuple elements...? What do you call this: MyTypeTuple[10] ? Is that an index *expression*? Internally, it's an IndexExp, but the tuple does not have expression elements, so the result is not an expression, it's a type. I would call that an expression as applied to a tuple regardless what kind of thing the result is. What about this: MyThing.Member <- where Member may be a type. Internally that's called a DotIdExp... so it's still an expression, even if it's result is not an expression. Can you show where my use of language in this DIP is inconsistent with these precedents?
Oct 30 2020
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/30/20 7:55 PM, Manu wrote:
 I was about to raise both those examples you showed here. I show 
 staticMap's implementation right there, and I also show types in tuples.
 The trouble as I see is that there's a spec language problem, where a 
 tuple element is a 'kind of thing' that I don't know what to call that.
Sorry, I must have missed it! I think a good term is "alias sequence" because AliasSeq in std.meta comprises exactly those. Generally relating this to stuff and terms in the language spec and stdlib docs would be great.
Oct 30 2020
next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Saturday, 31 October 2020 at 01:47:37 UTC, Andrei Alexandrescu 
wrote:
 On 10/30/20 7:55 PM, Manu wrote:
 I was about to raise both those examples you showed here. I 
 show staticMap's implementation right there, and I also show 
 types in tuples.
 The trouble as I see is that there's a spec language problem, 
 where a tuple element is a 'kind of thing' that I don't know 
 what to call that.
Sorry, I must have missed it! I think a good term is "alias sequence" because AliasSeq in std.meta comprises exactly those. Generally relating this to stuff and terms in the language spec and stdlib docs would be great.
You should call it a template parameter list.
Oct 30 2020
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Saturday, 31 October 2020 at 06:59:11 UTC, Stefan Koch wrote:
 You should call it a template parameter list.
It doesn't necessarily go to a template. I think the same class in dmd handles both though since you can pass values to a template too, just perhaps worth noting it is supposed to accept things that would cause a semantic error if passed to an actual template.
Oct 31 2020
prev sibling parent Manu <turkeyman gmail.com> writes:
On Sat, Oct 31, 2020 at 11:50 AM Andrei Alexandrescu via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On 10/30/20 7:55 PM, Manu wrote:
 I was about to raise both those examples you showed here. I show
 staticMap's implementation right there, and I also show types in tuples.
 The trouble as I see is that there's a spec language problem, where a
 tuple element is a 'kind of thing' that I don't know what to call that.
Sorry, I must have missed it! I think a good term is "alias sequence" because AliasSeq in std.meta comprises exactly those. Generally relating this to stuff and terms in the language spec and stdlib docs would be great.
So should I drop the language 'tuple' entirely? D doesn't actually propose to have tuples, I guess that's just the colloquial name for alias sequences.
Oct 31 2020
prev sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Friday, 30 October 2020 at 23:55:54 UTC, Manu wrote:
 I was about to raise both those examples you showed here. I show
 staticMap's implementation right there, and I also show types 
 in tuples.
 The trouble as I see is that there's a spec language problem, 
 where a tuple
 element is a 'kind of thing' that I don't know what to call 
 that.
I think "tuple element" is probably the best you can do. It's a little clunky, but clunky is better than ambiguous.
 What do you call this: MyTypeTuple[10]  ?
 Is that an index *expression*? Internally, it's an IndexExp, 
 but the tuple
 does not have expression elements, so the result is not an 
 expression, it's
 a type. I would call that an expression as applied to a tuple 
 regardless
 what kind of thing the result is.
 What about this: MyThing.Member  <- where Member may be a type. 
 Internally
 that's called a DotIdExp... so it's still an expression, even 
 if it's
 result is not an expression.
According to the grammar in the language spec, these are both IdentifierLists [1] when they appear in a context where a type is expected. In a context where an expression is expected, `MyTuple[10]` is an IndexExpression [2], and `MyThing.Member` is a PostfixExpression [3]. There is no such thing as a DotIdExp in the language spec. In general, if you need to refer to a particular syntactic construct, I think it's better to use the name from the language spec, rather than the DMD-internal class name. [1] https://dlang.org/spec/grammar.html#IdentifierList [2] https://dlang.org/spec/grammar.html#IndexExpression [3] https://dlang.org/spec/grammar.html#PostfixExpression
Oct 30 2020
parent reply Manu <turkeyman gmail.com> writes:
On Sat, Oct 31, 2020 at 12:05 PM Paul Backus via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Friday, 30 October 2020 at 23:55:54 UTC, Manu wrote:
 I was about to raise both those examples you showed here. I show
 staticMap's implementation right there, and I also show types
 in tuples.
 The trouble as I see is that there's a spec language problem,
 where a tuple
 element is a 'kind of thing' that I don't know what to call
 that.
I think "tuple element" is probably the best you can do. It's a little clunky, but clunky is better than ambiguous.
If I drop the term "tuple" for "alias sequence", then that results in "alias sequence element", which really doesn't roll off the tongue!
 What do you call this: MyTypeTuple[10]  ?
 Is that an index *expression*? Internally, it's an IndexExp,
 but the tuple
 does not have expression elements, so the result is not an
 expression, it's
 a type. I would call that an expression as applied to a tuple
 regardless
 what kind of thing the result is.
 What about this: MyThing.Member  <- where Member may be a type.
 Internally
 that's called a DotIdExp... so it's still an expression, even
 if it's
 result is not an expression.
According to the grammar in the language spec, these are both IdentifierLists [1] when they appear in a context where a type is expected. In a context where an expression is expected, `MyTuple[10]` is an IndexExpression [2], and `MyThing.Member` is a PostfixExpression [3]. There is no such thing as a DotIdExp in the language spec. In general, if you need to refer to a particular syntactic construct, I think it's better to use the name from the language spec, rather than the DMD-internal class name. [1] https://dlang.org/spec/grammar.html#IdentifierList [2] https://dlang.org/spec/grammar.html#IndexExpression [3] https://dlang.org/spec/grammar.html#PostfixExpression
Is "Alias Sequence" present in spec language? This really demonstrates how much D needs first-class tuples; this area of the language is a shit-fight, and essentially just a weird abuse of template argument lists mixed with `alias` and some implementation defined behaviour, which happens to look and feel a lot like a tuple.
Oct 31 2020
next sibling parent Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
On Saturday, 31 October 2020 at 23:09:31 UTC, Manu wrote:
 [..]

 Is "Alias Sequence" present in spec language?
https://dlang.org/articles/ctarguments.html
Oct 31 2020
prev sibling next sibling parent Abdulhaq <alynch4047 gmail.com> writes:
On Saturday, 31 October 2020 at 23:09:31 UTC, Manu wrote:
 Is "Alias Sequence" present in spec language?
 This really demonstrates how much D needs first-class tuples; 
 this area of
 the language is a shit-fight, and essentially just a weird 
 abuse of
 template argument lists mixed with `alias` and some 
 implementation defined
 behaviour, which happens to look and feel a lot like a tuple.
If tuples, tuple unpacking, compile time sequences et al. could be rationalised down to a simpler tuple concept (from the developer POV) then this would be "most marvelous" simplification. I have absolutely no idea if that is even vaguely possible, but it sounds great.
Nov 01 2020
prev sibling parent reply claptrap <clap trap.com> writes:
On Saturday, 31 October 2020 at 23:09:31 UTC, Manu wrote:
 On Sat, Oct 31, 2020 at 12:05 PM Paul Backus via Digitalmars-d 
 < digitalmars-d puremagic.com> wrote:
 Is "Alias Sequence" present in spec language?
 This really demonstrates how much D needs first-class tuples; 
 this area of
 the language is a shit-fight, and essentially just a weird 
 abuse of
 template argument lists mixed with `alias` and some 
 implementation defined
 behaviour, which happens to look and feel a lot like a tuple.
tuples already exists in other languages, in math / set theory, it's already a fairly well established idea and it seems a bit weird for D to invent its own name for what's essentially the same thing. To me "alias sequence" is an implementers name, it's named for how it's implemented not for the actual concept. It's like "when you see enum think manifest constant" "When you see AliasSeq think tuple" Or if instead of lambdas D decided to have "alias functions"... arrghh
Nov 01 2020
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Sunday, 1 November 2020 at 10:15:44 UTC, claptrap wrote:
 To me "alias sequence" is an implementers name, it's named for 
 how it's implemented not for the actual concept.
Yes, but tuples should have struct semantics, and structs hold values, not aliases. Anyway, this would all become moot if the ... operator was designed to work with all static length objects that provide index-access and .length.
Nov 01 2020
next sibling parent reply claptrap <clap trap.com> writes:
On Sunday, 1 November 2020 at 10:45:48 UTC, Ola Fosheim Grøstad 
wrote:
 On Sunday, 1 November 2020 at 10:15:44 UTC, claptrap wrote:
 To me "alias sequence" is an implementers name, it's named for 
 how it's implemented not for the actual concept.
Yes, but tuples should have struct semantics, and structs hold values, not aliases.
Why should they? Why cant a tuple hold aliases? That's essentially what AliasSeq is isnt it? I mean you shouldn't have to use arrays at run time and then entitylist at compile time, just because its holding something CT only. An array is an array. Maybe Im being naive or idealistic though.
Nov 01 2020
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Sunday, 1 November 2020 at 14:35:21 UTC, claptrap wrote:
 Why should they? Why cant a tuple hold aliases? That's 
 essentially what AliasSeq is isnt it?

 I mean you shouldn't have to use arrays at run time and then 
 entitylist at compile time, just because its holding something 
 CT only. An array is an array.
That's a good question, I guess you might hold aliases too now that you mention it. struct { int _0=42; alias _1=T; int length=2 } I guess you can. Hm.
Nov 01 2020
prev sibling parent Manu <turkeyman gmail.com> writes:
On Mon, Nov 2, 2020 at 12:41 AM claptrap via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Sunday, 1 November 2020 at 10:45:48 UTC, Ola Fosheim Gr=C3=B8stad
 wrote:
 On Sunday, 1 November 2020 at 10:15:44 UTC, claptrap wrote:
 To me "alias sequence" is an implementers name, it's named for
 how it's implemented not for the actual concept.
Yes, but tuples should have struct semantics, and structs hold values, not aliases.
Why should they? Why cant a tuple hold aliases? That's essentially what AliasSeq is isnt it? I mean you shouldn't have to use arrays at run time and then entitylist at compile time, just because its holding something CT only. An array is an array. Maybe Im being naive or idealistic though.
That's 1st-class-types talk ;) It would be great if D had first-class types. Stefan has ideas how to move in that direction, but my feeling has been that leadership is generally against it.
Nov 01 2020
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On Sun, Nov 1, 2020 at 8:50 PM Ola Fosheim Gr=C3=B8stad via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Sunday, 1 November 2020 at 10:15:44 UTC, claptrap wrote:
 To me "alias sequence" is an implementers name, it's named for
 how it's implemented not for the actual concept.
Yes, but tuples should have struct semantics, and structs hold values, not aliases.
Why? I don't agree with this at all. I actually expect tuples DON'T have struct semantics. The thing my DIP talks about are things that don't have struct semantics... what is that called? Anyway, this would all become moot if the ... operator was
 designed to work with all static length objects that provide
 index-access and .length.
Make a DIP then. I don't like that idea. It's problematic to know if you are dealing with a kind of thing that can be unrolled until much later in semantic when it should have already been done. It's trivial to implement a static unroll: `MyList[iota!(MyList.length)]...= ` Which can easily become: `alias StaticUnroll(T) =3D T[iota!(T.length)]...` -> `StaticUnroll!T`
Nov 01 2020
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Sunday, 1 November 2020 at 21:47:26 UTC, Manu wrote:
 Why? I don't agree with this at all. I actually expect tuples 
 DON'T have struct semantics.
Well, it is a good thing if they behave as immutable structs as you then can get a more uniform language.
 The thing my DIP talks about are things that don't have struct 
 semantics...
 what is that called?
I was wrong, in a way, as structs can have aliases as fields (I believe phobos Tuple does this?). Although it would be better if it was more akin to typeid so that they had a counterpart at runtime (so that a regular function can return all tuples), but that would require a language change. But it would also make what Stephan try to do easier? His typefunctions would just be regular functions returning a type-identifer.
 Make a DIP then. I don't like that idea. It's problematic to 
 know if you are dealing with a kind of thing that can be 
 unrolled until much later in semantic when it should have 
 already been done.
The semantic passes can determine when the operator should be evaluated.
Nov 01 2020
parent reply Manu <turkeyman gmail.com> writes:
On Mon, Nov 2, 2020 at 8:15 AM Ola Fosheim Gr=C3=B8stad via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Sunday, 1 November 2020 at 21:47:26 UTC, Manu wrote:
 Why? I don't agree with this at all. I actually expect tuples
 DON'T have struct semantics.
Well, it is a good thing if they behave as immutable structs as you then can get a more uniform language.
I think it is conceptually improper for a tuple to have a memory layout; especially considering tuples can hold elements that are types or aliases in addition to typed values.
 The thing my DIP talks about are things that don't have struct
 semantics...
 what is that called?
I was wrong, in a way, as structs can have aliases as fields (I believe phobos Tuple does this?). Although it would be better if it was more akin to typeid so that they had a counterpart at runtime (so that a regular function can return all tuples), but that would require a language change. But it would also make what Stephan try to do easier? His typefunctions would just be regular functions returning a type-identifer.
I think type functions are a great initiative, and I've talked with him about that a lot. I don't think this DIP competes with type functions. I also think type functions will need a LOT of work to materialise.
 Make a DIP then. I don't like that idea. It's problematic to
 know if you are dealing with a kind of thing that can be
 unrolled until much later in semantic when it should have
 already been done.
The semantic passes can determine when the operator should be evaluated.
Under my DIP, the map is applied very early, pre-semantic. The resulting tuple must compile in context and make semantic sense, and this is very important such that it can be used in a wide variety of interesting contexts. It's also extremely complicated to know what the output of `...` applied to an array-like thing should be? Is it a tuple? If you apply `...` to an array or a range, and it becomes a tuple, that is probably going to reveal serious semantic problems. Imagine this: void fun(MyRange r) { ... } MyRange constantRange; fun(constantRange); // <-- function receives range as argument fun(expr(constantRange)...); // <-- the function call fails because the range got turned into a tuple. Or this: immutable int[] allTheThings =3D [ ... ]; alias Selection =3D AliasSeq!(5, 1, 15); alias res =3D allTheThings[Selection]...; // <-- we have an array, and a tuple both participating in the map; if `...` applied to array-like-things, then this extremely important pattern would be impossible If it attempts a parallel expansion as is specified in the DIP, then immediately, the lengths do not match, but more importantly, the expression doesn't even make functional sense anymore. This DIP applies to tuples, specifically, and exclusively. You need to design a completely different DIP if you think that's wrong.
Nov 01 2020
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Monday, 2 November 2020 at 03:49:41 UTC, Manu wrote:
 On Mon, Nov 2, 2020 at 8:15 AM Ola Fosheim Grøstad via 
 Digitalmars-d < digitalmars-d puremagic.com> wrote:
 Well, it is a good thing if they behave as immutable structs 
 as you then can get a more uniform language.
I think it is conceptually improper for a tuple to have a memory layout; especially considering tuples can hold elements that are types or aliases in addition to typed values.
D should reduce the number of types you have to account for in generic code.
 It's also extremely complicated to know what the output of 
 `...` applied to
 an array-like thing should be? Is it a tuple? If you apply 
 `...` to an
 array or a range, and it becomes a tuple, that is probably 
 going to reveal
 serious semantic problems.
It should not be a tuple, it should be an extension of a comma list. Think splat operator. The compiler only needs to know the length of the sequence in order to expand.
   fun(constantRange); // <-- function receives range as argument
   fun(expr(constantRange)...); // <-- the function call fails
I dont understand this example.
 Or this:
   immutable int[] allTheThings = [ ... ];
   alias Selection = AliasSeq!(5, 1, 15);
   alias res = allTheThings[Selection]...; // <-- we have an 
 array, and a
 tuple both participating in the map; if `...` applied to 
 array-like-things,
 then this extremely important pattern would be impossible
I suggested explicit indexing, so not a problem.
Nov 01 2020
parent reply Manu <turkeyman gmail.com> writes:
On Mon, Nov 2, 2020 at 4:30 PM Ola Fosheim Gr=C3=B8stad via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Monday, 2 November 2020 at 03:49:41 UTC, Manu wrote:
 On Mon, Nov 2, 2020 at 8:15 AM Ola Fosheim Gr=C3=B8stad via
 Digitalmars-d < digitalmars-d puremagic.com> wrote:
 Well, it is a good thing if they behave as immutable structs
 as you then can get a more uniform language.
I think it is conceptually improper for a tuple to have a memory layout; especially considering tuples can hold elements that are types or aliases in addition to typed values.
D should reduce the number of types you have to account for in generic code.
I'm not sure what this means.
 It's also extremely complicated to know what the output of
 `...` applied to
 an array-like thing should be? Is it a tuple? If you apply
 `...` to an
 array or a range, and it becomes a tuple, that is probably
 going to reveal
 serious semantic problems.
It should not be a tuple, it should be an extension of a comma list. Think splat operator.
My DIP is not like that. The compiler only needs to know the length of the sequence in
 order to expand.

   fun(constantRange); // <-- function receives range as argument
   fun(expr(constantRange)...); // <-- the function call fails
I dont understand this example.
The type is lost, so by applying a map expression to an array-like-thing, you can't use it in its original context anymore.
 Or this:
   immutable int[] allTheThings =3D [ ... ];
   alias Selection =3D AliasSeq!(5, 1, 15);
   alias res =3D allTheThings[Selection]...; // <-- we have an
 array, and a
 tuple both participating in the map; if `...` applied to
 array-like-things,
 then this extremely important pattern would be impossible
I suggested explicit indexing, so not a problem.
I don't understand this comment.
Nov 02 2020
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Monday, 2 November 2020 at 09:45:48 UTC, Manu wrote:
 On Mon, Nov 2, 2020 at 4:30 PM Ola Fosheim Grøstad via 
 Digitalmars-d < digitalmars-d puremagic.com> wrote:
 D should reduce the number of types you have to account for in 
 generic code.
I'm not sure what this means.
Tuples should work with all generic code that is willing to take a struct as input.
 I suggested explicit indexing, so not a problem.
I don't understand this comment.
Assume tuple t1 and t2 IN: f("hello", tuple(t1[_], t2),...] OUT: f("hello", tuple(t1[0], t2),tuple(t1[1], t2), tuple(t1[2], t2)]
Nov 02 2020
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/1/20 5:15 AM, claptrap wrote:
 On Saturday, 31 October 2020 at 23:09:31 UTC, Manu wrote:
 On Sat, Oct 31, 2020 at 12:05 PM Paul Backus via Digitalmars-d < 
 digitalmars-d puremagic.com> wrote:
 Is "Alias Sequence" present in spec language?
 This really demonstrates how much D needs first-class tuples; this 
 area of
 the language is a shit-fight, and essentially just a weird abuse of
 template argument lists mixed with `alias` and some implementation 
 defined
 behaviour, which happens to look and feel a lot like a tuple.
tuples already exists in other languages, in math / set theory, it's already a fairly well established idea and it seems a bit weird for D to invent its own name for what's essentially the same thing.
It isn't the same thing.
Nov 01 2020
next sibling parent reply Delt <detla.bravo gmail.com> writes:
On Sunday, 1 November 2020 at 16:37:19 UTC, Andrei Alexandrescu 
wrote:
 On 11/1/20 5:15 AM, claptrap wrote:
 On Saturday, 31 October 2020 at 23:09:31 UTC, Manu wrote:
 On Sat, Oct 31, 2020 at 12:05 PM Paul Backus via 
 Digitalmars-d < digitalmars-d puremagic.com> wrote:
 Is "Alias Sequence" present in spec language?
 This really demonstrates how much D needs first-class tuples; 
 this area of
 the language is a shit-fight, and essentially just a weird 
 abuse of
 template argument lists mixed with `alias` and some 
 implementation defined
 behaviour, which happens to look and feel a lot like a tuple.
tuples already exists in other languages, in math / set theory, it's already a fairly well established idea and it seems a bit weird for D to invent its own name for what's essentially the same thing.
It isn't the same thing.
Essentially the same != the same Addition using integers is still called addition even if it isn't the same thing as mathematical arithmetic.
Nov 01 2020
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/1/20 1:37 PM, Delt wrote:
 On Sunday, 1 November 2020 at 16:37:19 UTC, Andrei Alexandrescu wrote:
 On 11/1/20 5:15 AM, claptrap wrote:
 On Saturday, 31 October 2020 at 23:09:31 UTC, Manu wrote:
 On Sat, Oct 31, 2020 at 12:05 PM Paul Backus via Digitalmars-d < 
 digitalmars-d puremagic.com> wrote:
 Is "Alias Sequence" present in spec language?
 This really demonstrates how much D needs first-class tuples; this 
 area of
 the language is a shit-fight, and essentially just a weird abuse of
 template argument lists mixed with `alias` and some implementation 
 defined
 behaviour, which happens to look and feel a lot like a tuple.
tuples already exists in other languages, in math / set theory, it's already a fairly well established idea and it seems a bit weird for D to invent its own name for what's essentially the same thing.
It isn't the same thing.
Essentially the same != the same
They are very different.
Nov 01 2020
prev sibling parent reply claptrap <clap trap.com> writes:
On Sunday, 1 November 2020 at 16:37:19 UTC, Andrei Alexandrescu 
wrote:
 On 11/1/20 5:15 AM, claptrap wrote:
 On Saturday, 31 October 2020 at 23:09:31 UTC, Manu wrote:
 On Sat, Oct 31, 2020 at 12:05 PM Paul Backus via 
 Digitalmars-d < digitalmars-d puremagic.com> wrote:
 Is "Alias Sequence" present in spec language?
 This really demonstrates how much D needs first-class tuples; 
 this area of
 the language is a shit-fight, and essentially just a weird 
 abuse of
 template argument lists mixed with `alias` and some 
 implementation defined
 behaviour, which happens to look and feel a lot like a tuple.
tuples already exists in other languages, in math / set theory, it's already a fairly well established idea and it seems a bit weird for D to invent its own name for what's essentially the same thing.
It isn't the same thing.
Why isn't it the same thing? An AliasSeq and a tuple are both an ordered list of elements. That one holds values and the other holds aliases is down to the context in which either is used i think. So if you say we need to differentiate them, maybe thats a point, but then maybe it shouldn't need to be like that. Maybe they should be the same thing.
Nov 01 2020
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Sunday, 1 November 2020 at 19:24:07 UTC, claptrap wrote:
 Why isn't it the same thing? An AliasSeq and a tuple are both 
 an ordered list of elements. That one holds values and the
I don't know, but what it is, is described here: https://dlang.org/articles/ctarguments.html
Nov 01 2020
prev sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
After reading much of the discussion here, a lot of it is about the 
terminology I think and not substance.

It's clear to me that the way the DIP works is:

something...

expands all tuples within "something" according to the DIP rules.

So what is something? Depends on where it is used. My understanding is 
that the *result* is a tuple/AliasSeq, but the *input* could be anything 
that *contains* a tuple. It could be a list of types, it could be a 
template instantiation, it could be an alias, it could be an argument 
list. I think the only place it can't be used is as a parameter list (as 
... is already defined there).

The concept itself is great, and powerful (I played with the 
implementation a while back).

What I think this DIP is missing is a good name for the "something".

I still also would like to know when I need to enclose the something in 
parentheses.

In the DIP for example:

alias Values = AliasSeq!(1, 2, 3);
alias Types = AliasSeq!(int, short, float);
pragma(msg, cast(Types)Values...);

 cast(int)1, cast(short)2, cast(float)3
How far back does the ... apply? For example, a postfix ++ operator does not go back as far as this suggests: cast(int)foo++; => cast(int)(foo++); So it seems logical that the above evaluates like: cast(Types)(Values...) But your example suggests otherwise. This is why I asked about operator precedence. One further issue that still hasn't been addressed (maybe you are planning on addressing it, but just haven't commented on my feedback), what about nesting? (something... + 5)... What happens here? -Steve
Nov 02 2020