February 17, 2018
On 16.02.2018 21:16, Jonathan M Davis wrote:
> On Friday, February 16, 2018 21:01:02 Martin Nowak via Digitalmars-d wrote:
>> On 01/14/2018 12:21 AM, Timon Gehr wrote:
>>>> what would be the equivalent of this ?
>>>> ` writeln(tuple!("x", "y", "z")(2, 3, 4).y); `
>>>
>>> It would continue to work the same way.
>>>
>>> I did consider adding a proposal for built-in named tuple syntax:
>>>
>>> writeln((x: 2, y: 3, z: 4).y);
>>>
>>> (int a, double b) t = (a: 1, b: 2.0);
>>> int x = t.a;
>>> double y = t.b;
>>
>> Tuples are anonymous bundles, when you want a product type with field
>> names use a struct.
> 
> That's not necessarily unreasonable, but std.typecons.Tuple is frequently
> used as a convenient way to return a group of values, and the trend has been
> towards using named values, because those are easier to deal with as return
> values, because they're somewhat self-documenting at that point, and they're
> less error-prone. So, if we're talking about adding more complete tuples to
> the language, if they don't have support for names, you then have the
> problem of whether it's better to use the built-in tuples or something like
> std.typecons.Tuple with named values, and there's a pretty strong argument
> at that point that it's better to use the named tuples and lose whatever
> benefits the built-in tuples might provide, because the named tuples result
> in more maintainable code.
> 
> - Jonathan M Davis
> 

This is not really problematic. Note that the /only/ improvement in the DIP that does not apply to library tuples is the tuple construction syntax.
February 17, 2018
On 16.02.2018 21:01, Martin Nowak wrote:
> On 01/14/2018 12:21 AM, Timon Gehr wrote:
>>> what would be the equivalent of this ?
>>> ` writeln(tuple!("x", "y", "z")(2, 3, 4).y); `
>>
>> It would continue to work the same way.
>>
>> I did consider adding a proposal for built-in named tuple syntax:
>>
>> writeln((x: 2, y: 3, z: 4).y);
>>
>> (int a, double b) t = (a: 1, b: 2.0);
>> int x = t.a;
>> double y = t.b;
> 
> Tuples are anonymous bundles, when you want a product type with field
> names use a struct.
> 

I agree, but Phobos does not.
February 17, 2018
On 16.02.2018 21:48, H. S. Teoh wrote:
> On Fri, Feb 16, 2018 at 01:16:13PM -0700, Jonathan M Davis via Digitalmars-d wrote:
>> On Friday, February 16, 2018 21:01:02 Martin Nowak via Digitalmars-d wrote:
>>> On 01/14/2018 12:21 AM, Timon Gehr wrote:
>>>>> what would be the equivalent of this ?
>>>>> ` writeln(tuple!("x", "y", "z")(2, 3, 4).y); `
>>>>
>>>> It would continue to work the same way.
>>>>
>>>> I did consider adding a proposal for built-in named tuple syntax:
>>>>
>>>> writeln((x: 2, y: 3, z: 4).y);
>>>>
>>>> (int a, double b) t = (a: 1, b: 2.0);
>>>> int x = t.a;
>>>> double y = t.b;
>>>
>>> Tuples are anonymous bundles, when you want a product type with
>>> field names use a struct.
>>
>> That's not necessarily unreasonable, but std.typecons.Tuple is frequently
>> used as a convenient way to return a group of values, and the trend has been
>> towards using named values, because those are easier to deal with as return
>> values, because they're somewhat self-documenting at that point, and they're
>> less error-prone. So, if we're talking about adding more complete tuples to
>> the language, if they don't have support for names, you then have the
>> problem of whether it's better to use the built-in tuples or something like
>> std.typecons.Tuple with named values, and there's a pretty strong argument
>> at that point that it's better to use the named tuples and lose whatever
>> benefits the built-in tuples might provide, because the named tuples result
>> in more maintainable code.
> [...]
> 
> Tuples with named fields are essentially anonymous structs.  If we had
> those, 60% of what this DIP addresses would already have been solved.
> Cf.:
> 
> 	https://forum.dlang.org/post/kfbnuc$1cro$1@digitalmars.com
> 
> 
> T
> 

You got that number a bit too high.
The DIP is mostly about tuple unpacking.
February 17, 2018
On 16.02.2018 20:51, Martin Nowak wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA512
> 
> On 01/12/2018 11:44 PM, Timon Gehr wrote:
>> As promised [1], I have started setting up a DIP to improve tuple
>> ergonomics in D:
>>
>> https://github.com/tgehr/DIPs/blob/tuple-syntax/DIPs/DIP1xxx-tg.md
> 
> Pardon me if things have been said already, can't really read through
> all the thread.
> 
> - - Regarding underscore as placeholder.
> 
> https://issues.dlang.org/show_bug.cgi?id=13522
> 

Thanks! I'll add a link to the enhancement to the DIP.

> - - Regarding the "limitation"
> 
> Maybe you want some auto-packing feature there? Doesn't seem too bad,
> we could come up with sth. when this turns out to become a common
> nuisance.
> Have you considered to lower (1, 2, 3)[0 .. 2] to tuple(tuple(1, 2,
> 3)[0 .. 2]) or using a non-std.typecons tuple where slicing does not
> expand?
> ...

I think this is technically a good idea, but there are drawbacks: (i) the language does not support this for user-defined types, ideally we avoid adding more built-in magic, and (ii) having two different types will be confusing to newcomers. ("Which of the two seemingly equivalent Tuple constructs should I use?")

> - - closed tuples?
> 
> The reference to std.typecons.tuple implies contiguous struct memory
> layout (closed tuples).
> This is a bit subtle for unpacking assignments which lower to
> 
> AliasSeq!(x, y) = tuple(y, x)[];
> 
> so on the left-hand side of an assignment, the syntax refers to a
> non-contiguous (open) tuple.
> ...

I don't think this is the best way to think about it. Syntactically, the left-hand side contains two non-contiguous variables x and y and uses their values to form a contiguous tuple, but as it is the left-hand side of an assignment, the operation is actually performed in the opposite direction. This is a bit as if D supported assignments of the form:

int a;
a + 1 = 3;
assert(a == 2); // computed using the inverse: a = 3 - 1

Of course, this is independent of the actual implementation strategy chosen.

> Declarations like
> 
> auto (a, b) = (1, 2);
> 
> also seem to declare an open tuple (non-contiguous memory).
> ...

Yes, the idea is that this would declare multiple independent variables.

> I assume that unpacking function arguments behaves similarly, i.e. on
> ABI level, each argument is passed separately.
> ...

I think the ABI should be unaffected in this case (it is just syntax sugar for unpacking the tuple argument immediately at the start of the called function, i.e. it is a callee-site construct that happens to sometimes make the signature prettier for the caller also). I will clarify this point.

> 
> Overall looks really good. I think that would make for a great
> addition to the language.
> ...

Thanks! I'll make sure to incorporate your points when I'll finally get around to updating the DIP based on the forum feedback.
February 19, 2018
On Friday, 12 January 2018 at 22:44:48 UTC, Timon Gehr wrote:
> As promised [1], I have started setting up a DIP to improve tuple ergonomics in D:
>
> https://github.com/tgehr/DIPs/blob/tuple-syntax/DIPs/DIP1xxx-tg.md
>
>
> This DIP aims to make code like the following valid D:
...

Would this DIP allow array unpacking?

eg, see this rust snippet from https://gist.github.com/anonymous/9cfc3d1b057f7a137ccbfb94bf4bfcef

```
fn main() {
  let (infile, colname, repl, outfile) = std::env::args().skip(1).tuples().next().expect("Invalid args\n");
}
```

what would be the D equivalent under this DIP? (just for the array unpacking part )



February 20, 2018
On 20.02.2018 00:19, timotheecour wrote:
> On Friday, 12 January 2018 at 22:44:48 UTC, Timon Gehr wrote:
>> As promised [1], I have started setting up a DIP to improve tuple ergonomics in D:
>>
>> https://github.com/tgehr/DIPs/blob/tuple-syntax/DIPs/DIP1xxx-tg.md
>>
>>
>> This DIP aims to make code like the following valid D:
> ...
> 
> Would this DIP allow array unpacking?
> ...

Yes, but would not be built-in.

> eg, see this rust snippet from https://gist.github.com/anonymous/9cfc3d1b057f7a137ccbfb94bf4bfcef
> 
> ```
> fn main() {
>    let (infile, colname, repl, outfile) = std::env::args().skip(1).tuples().next().expect("Invalid args\n");
> }
> ```
> 
> what would be the D equivalent under this DIP? (just for the array unpacking part )
> 
> 
> 

For a suitable implementation of "unpack":

void main(){
    auto (infile, colname, repl, outfile) = args[1..$].unpack!4("Invalid args\n");
}

Unfortunately, there is no good way to get rid of "4", as D does not have backwards type inference.
February 20, 2018
On 20.02.2018 00:43, Timon Gehr wrote:
> 
> void main(){
>      auto (infile, colname, repl, outfile) = args[1..$].unpack!4("Invalid args\n");
> }

Actually:

void main(string[] args){
    auto (infile, colname, repl, outfile) = args[1..$].unpack!4("Invalid args\n");
}

February 19, 2018
great! maybe worth adding to DIP? (even though `unpack` would be
(IIUC) a pure library solution on top of this DIP)

and that would work too I guess?
```
string[4] args=...;
auto (infile, colname, repl, outfile) = args.unpack;
```


On Mon, Feb 19, 2018 at 3:47 PM, Timon Gehr via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On 20.02.2018 00:43, Timon Gehr wrote:
>>
>>
>> void main(){
>>      auto (infile, colname, repl, outfile) = args[1..$].unpack!4("Invalid
>> args\n");
>> }
>
>
> Actually:
>
> void main(string[] args){
>
>     auto (infile, colname, repl, outfile) = args[1..$].unpack!4("Invalid
> args\n");
> }
>
February 20, 2018
On 20.02.2018 00:53, Timothee Cour wrote:
> great! maybe worth adding to DIP? (even though `unpack` would be
> (IIUC) a pure library solution on top of this DIP)
> ...

Yes. I'll add it to the use cases.

> and that would work too I guess?
> ```
> string[4] args=...;
> auto (infile, colname, repl, outfile) = args.unpack;
> ```

Sure! Also, this:

void main(string[] args){
    enforce(args.length==5, "Invalid args");
    auto (infile, colname, repl, outfile) = args[1..5].unpack;
    // ...
}
February 19, 2018
On Mon, Feb 19, 2018 at 4:05 PM, Timon Gehr via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On 20.02.2018 00:53, Timothee Cour wrote:
>>
> Sure! Also, this:
>
> void main(string[] args){
>     enforce(args.length==5, "Invalid args");
>     auto (infile, colname, repl, outfile) = args[1..5].unpack;
>     // ...
> }


how does that latter example work?