digitalmars.D - Discussion Thread: DIP 1037--Add Unary Operator ...--Community Review
- Mike Parker (21/21) Oct 27 2020 This is the discussion thread for the first round of Community
- Mike Parker (3/8) Oct 27 2020 The feedback thread is here:
- Jacob Carlborg (12/15) Oct 28 2020 Is there a risk of causing some form of ambiguity with variadic
- Manu (5/20) Oct 28 2020 What does `c` mean?
- Manu (8/33) Oct 28 2020 Your example `void c(int...)` mangles as `void c(int)`, and it's also
- Q. Schroll (53/60) Nov 02 2020 No, because the DIP does not propose anything with types. In the
- Manu (10/72) Nov 02 2020 Thank you for this analysis. This is useful. I'll confirm the DIP's spec
- Q. Schroll (19/21) Nov 02 2020 It does, if it should work on types. In the easiest case, if you
- Manu (22/43) Nov 02 2020 You're right, and a change like that does exist in my implementation
- Andrei Alexandrescu (14/15) Nov 03 2020 By the way in C++ the expansion applies to so-called patterns, not
- Stefan Koch (8/24) Nov 03 2020 A Type in practice is just an expression.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (6/9) Nov 03 2020 Is it though? It would be nice if alias could bind to
- Stefan Koch (5/16) Nov 04 2020 I said all types are expressions.
- Q. Schroll (25/35) Nov 04 2020 I really don't think that such a special case is necessary. Maybe
- Manu (6/41) Nov 05 2020 Good point. Except elipsis would be inside the parens.
- Q. Schroll (7/10) Nov 02 2020 Probably you didn't care that much about the formal grammar and
- Andrei Alexandrescu (3/8) Nov 02 2020 I thought the grammar is fairly complete, no? It's the semantics that's
- Manu (8/16) Nov 02 2020 It may be complete, but it's difficult to relate to the code, and when
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (13/15) Oct 28 2020 I think it should be made more generic and flexible. Make it work
- Manu (21/35) Oct 28 2020 On Wed, Oct 28, 2020 at 11:35 PM Ola Fosheim Gr=C3=B8stad via Digitalmar...
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (13/31) Oct 28 2020 That was an example. Reverse. Every other etc.
- Paul Backus (4/8) Oct 28 2020 You can add an initial value outside of the fold expression:
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (7/9) Oct 28 2020 Ok, but the problem is in generic code. You could adopt init as
- Paul Backus (5/16) Oct 28 2020 Generic code can deal with this the same way std.algorithm.reduce
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (6/9) Oct 28 2020 What I meant is what if the library author provided a function
- Paul Backus (6/16) Oct 28 2020 The library author could just as easily use `T.init` as the
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (7/11) Oct 28 2020 No, it is common to fold with 0 for addition and 1 for
- Paul Backus (8/17) Oct 28 2020 The bug you described in your previous post can only ever occur
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (4/10) Oct 28 2020 No, the bug I described is when you take an empty tuple. What
- Guillaume Piolat (10/14) Oct 28 2020 The DIP brings compile-time improvements, but this is a feature
- Paul Backus (6/21) Oct 28 2020 As is amply evident from the history of __traits, making
- H. S. Teoh (11/20) Oct 28 2020 [...]
- Manu (5/19) Oct 28 2020 I'm not sure what you mean it's reserved for the standard library? That ...
- Steven Schveighoffer (14/24) Oct 29 2020 I am confused by this. Isn't it fine to work with expressions only?
- Andrei Alexandrescu (6/35) Oct 30 2020 What would the implementation of staticMap with the DIP look like? As
- Steven Schveighoffer (11/30) Oct 30 2020 It has the implementation right in the DIP:
- Manu (24/54) Oct 30 2020 I was about to raise both those examples you showed here. I show
- Andrei Alexandrescu (5/9) Oct 30 2020 Sorry, I must have missed it!
- Stefan Koch (3/15) Oct 30 2020 You should call it a template parameter list.
- Adam D. Ruppe (6/7) Oct 31 2020 It doesn't necessarily go to a template. I think the same class
- Manu (5/14) Oct 31 2020 So should I drop the language 'tuple' entirely? D doesn't actually propo...
- Paul Backus (15/35) Oct 30 2020 I think "tuple element" is probably the best you can do. It's a
- Manu (9/45) Oct 31 2020 If I drop the term "tuple" for "alias sequence", then that results in
- Petar Kirov [ZombineDev] (2/4) Oct 31 2020 https://dlang.org/articles/ctarguments.html
- Abdulhaq (6/14) Nov 01 2020 If tuples, tuple unpacking, compile time sequences et al. could
- claptrap (11/21) Nov 01 2020 tuples already exists in other languages, in math / set theory,
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (6/8) Nov 01 2020 Yes, but tuples should have struct semantics, and structs hold
- claptrap (8/13) Nov 01 2020 Why should they? Why cant a tuple hold aliases? That's
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (5/10) Nov 01 2020 That's a good question, I guess you might hold aliases too now
- Manu (6/20) Nov 01 2020 That's 1st-class-types talk ;)
- Manu (14/21) Nov 01 2020 Why? I don't agree with this at all. I actually expect tuples DON'T have
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (13/22) Nov 01 2020 Well, it is a good thing if they behave as immutable structs as
- Manu (34/56) Nov 01 2020 I think it is conceptually improper for a tuple to have a memory layout;
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (9/33) Nov 01 2020 D should reduce the number of types you have to account for in
- Manu (8/41) Nov 02 2020 I'm not sure what this means.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (8/17) Nov 02 2020 Tuples should work with all generic code that is willing to take
- Andrei Alexandrescu (2/16) Nov 01 2020 It isn't the same thing.
- Delt (5/23) Nov 01 2020 Essentially the same != the same
- Andrei Alexandrescu (2/22) Nov 01 2020 They are very different.
- claptrap (8/26) Nov 01 2020 Why isn't it the same thing? An AliasSeq and a tuple are both an
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (3/5) Nov 01 2020 I don't know, but what it is, is described here:
- Steven Schveighoffer (33/34) Nov 02 2020 After reading much of the discussion here, a lot of it is about the
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
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
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.mdIs 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
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:What does `c` mean? Is it possible that c and d are identical things here, even with my DIP in place?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).
Oct 28 2020
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:What does `c` mean? Is it possible that c and d are identical things here, even with my DIP in place?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).
Oct 28 2020
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: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/DeGZF7This 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.mdIs there a risk of causing some form of ambiguity with variadic functions?
Nov 02 2020
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: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.On Tuesday, 27 October 2020 at 10:54:07 UTC, Mike Parker wrote:https://github.com/dlang/DIPs/blob/ba81eec84ddf0aeeb2cb652743b292455ec8c62a/DIPs/DIP1037.mdThis is the discussion thread for the first round of Community Review of DIP 1037, "Add Unary Operator ...":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
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
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: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.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
On 11/3/20 2:05 AM, Manu wrote:MyTemplate!(expr...) <-- appearance in template parameter listsBy 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
On Tuesday, 3 November 2020 at 13:46:20 UTC, Andrei Alexandrescu wrote:On 11/3/20 2:05 AM, Manu wrote: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.MyTemplate!(expr...) <-- appearance in template parameter listsBy 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
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
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:I said all types are expressions. (Even though the language does not admit it yet.) Not all expressions are types.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 04 2020
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
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: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. theThere'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.`...` 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
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
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
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 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.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
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
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: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 (initialThis 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.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
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.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.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.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
On Wednesday, 28 October 2020 at 14:56:10 UTC, Ola Fosheim Grøstad wrote:You can add an initial value outside of the fold expression: false || Tup == 10 || ...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.
Oct 28 2020
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
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: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.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
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
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: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.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
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
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 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.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.
Oct 28 2020
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
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
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: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.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
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
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: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.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
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
On 10/29/20 9:48 AM, Steven Schveighoffer wrote:From the Feedback Thread:I don't think it works that way, no.* 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.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
On 10/30/20 2:29 PM, Andrei Alexandrescu wrote:On 10/29/20 9:48 AM, Steven Schveighoffer wrote:It has the implementation right in the DIP: alias staticMap(alias F, T...) = F!T...;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.In the examples there are. e.g.: alias Values = AliasSeq!(1, 2, 3); alias Types = AliasSeq!(int, short, float); pragma(msg, cast(Types)Values...);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.cast(int)1, cast(short)2, cast(float)3Maybe 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
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: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?On 10/29/20 9:48 AM, Steven Schveighoffer wrote:It has the implementation right in the DIP: alias staticMap(alias F, T...) = F!T...;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.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. -StevePerhaps 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
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
On Saturday, 31 October 2020 at 01:47:37 UTC, Andrei Alexandrescu wrote:On 10/30/20 7:55 PM, Manu wrote:You should call it a template parameter list.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
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
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: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.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 31 2020
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
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:If I drop the term "tuple" for "alias sequence", then that results in "alias sequence element", which really doesn't roll off the tongue!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 "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.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 31 2020
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
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
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
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
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: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.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.
Nov 01 2020
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
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: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.On Sunday, 1 November 2020 at 10:15:44 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. Maybe Im being naive or idealistic though.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.
Nov 01 2020
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: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 wasTo 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.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
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
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: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.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 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.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 toUnder 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.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
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:D should reduce the number of types you have to account for in generic code.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.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 failsI 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 impossibleI suggested explicit indexing, so not a problem.
Nov 01 2020
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:I'm not sure what this means.On Mon, Nov 2, 2020 at 8:15 AM Ola Fosheim Gr=C3=B8stad via Digitalmars-d < digitalmars-d puremagic.com> wrote:D should reduce the number of types you have to account for in generic code.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.It's also extremely complicated to know what the output ofMy DIP is not like that. The compiler only needs to know the length of the sequence in`...` 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.order to expand.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.fun(constantRange); // <-- function receives range as argument fun(expr(constantRange)...); // <-- the function call failsI dont understand this example.I don't understand this comment.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 impossibleI suggested explicit indexing, so not a problem.
Nov 02 2020
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:Tuples should work with all generic code that is willing to take a struct as input.D should reduce the number of types you have to account for in generic code.I'm not sure what this means.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)]I suggested explicit indexing, so not a problem.I don't understand this comment.
Nov 02 2020
On 11/1/20 5:15 AM, claptrap wrote:On Saturday, 31 October 2020 at 23:09:31 UTC, Manu wrote:It isn't the same thing.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.
Nov 01 2020
On Sunday, 1 November 2020 at 16:37:19 UTC, Andrei Alexandrescu wrote:On 11/1/20 5:15 AM, claptrap wrote:Essentially the same != the same Addition using integers is still called addition even if it isn't the same thing as mathematical arithmetic.On Saturday, 31 October 2020 at 23:09:31 UTC, Manu wrote:It isn't the same thing.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.
Nov 01 2020
On 11/1/20 1:37 PM, Delt wrote:On Sunday, 1 November 2020 at 16:37:19 UTC, Andrei Alexandrescu wrote:They are very different.On 11/1/20 5:15 AM, claptrap wrote:Essentially the same != the sameOn Saturday, 31 October 2020 at 23:09:31 UTC, Manu wrote:It isn't the same thing.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.
Nov 01 2020
On Sunday, 1 November 2020 at 16:37:19 UTC, Andrei Alexandrescu wrote:On 11/1/20 5:15 AM, 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 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.On Saturday, 31 October 2020 at 23:09:31 UTC, Manu wrote:It isn't the same thing.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.
Nov 01 2020
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 theI don't know, but what it is, is described here: https://dlang.org/articles/ctarguments.html
Nov 01 2020
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)3How 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