March 29, 2013 Re: DIP32: Uniform tuple syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile Attachments:
| 2013/3/29 bearophile <bearophileHUGS@lycos.com> > One handy tuple syntax in Haskell allows you to name both the items of a tuple and it whole: > > void foo(t2@{int a, string b}) { > // here a and b are tuple items and t2 is the whole tuple. > } > auto t1@{x, y} = {10, "hi"}; > foo(t1); > It will introduce a kind of "reference variable" to D. auto t1@{x, y} = {10, "hi"}; assert(&t1[0] == &x); // t1[0] and x may refer same address on stack. Such case, you can repeat pack and unpack. void foo({int a, string b}) { // auto t2 = {a, b}; // make tuple by copy, or // {a, b} = {1, 2}; // make pack and use it immediately } auto {x, y} = {10, "hi"}; foo({x, y}); > auto tup = {}; // zero-element tuple (Syntax meaning will be changed!) > > Nullary tuples are not that useful in D. Scala doesn't even have a short literal for them. > > So a longer syntax like this is acceptable: > > auto tup = Tuple(); > This is for the consistency of language elements. If you want to zero-parameter lambda, you can write like follows. auto fn = (){}; auto fn = {;}; > - - - - - - - - - - - - > > This is nice, so we are merging tuple types with tuples, this will simplify D language: > > // declare tuple value by using explicit tuple type > {int, string} tup = {1, "hi"}; > > alias TL = {int, string[], double[string]}; // types > > > But one thing to remember in the document is that here T1 and T2 are different, because your tuples do not auto-flatten as TypeTuples currently do: > > alias T1 = {float, double, real}; > alias T2 = {float, double, {real}}; > It would need more description. I'll explain about that. - - - - - - - - - - - - > > foreach (Float; {float, double, real}) { ... } > > I think you meant to put a variable name there. > Float is the iterated type. > - - - - - - - - - - - - > > {1} // one-element tuple > > I presume this too will be accepted as 1-tuple: > > {1,} > Currently D allows redundant commas in some places. void foo(int x, int y,) {} enum E { a = 1, b = 2, } auto arr = [1,2,3,]; So, compiler would accept following tuples. auto tup = {1,}; auto tup = {1,"hi",}; > - - - - - - - - - - - - > > {c, $} = tup; // Rewritten as: c = tup[0]; > > $ is used for array lengths, so it's not so good to overload it to mean "don't care" too. > > Alternative syntaxes: > > {c, $_} = tup; > {c, @} = tup; > {c, @_} = tup; > {c, $$} = tup; > {c, {}} = tup; > {c, {_}} = tup; > {c, $~} = tup; > {c, @~= tup; > etc. > Placeholder token is debatable. > - - - - - - - - - - - - > > > if (auto {1, y} = tup) { > // If the first element of tup (tup[0]) is equal to 1, > // y captures the second element of tup (tup[1]). > } > > > I suggest to leave that pattern matching plus conditional to a future refinement of tuple implementation (a second stage. And remove it from this first stage proposal. So I suggest to split your proposal in two successive proposals). It seems handy, but D programmers need some time to go there. > For complex tuple unpacking requires the part of pattern matching. auto tup = {1, {2,3,4,5,6}} auto {x, {$, y, ...}} = tup; // makes nested tuple pattern for unpacking assert(x == 1); assert(y == 3); So I'd like to keep one DIP. > - - - - - - - - - - - - > > switch (tup) { > case {1, 2}: > case {$, 2}: > case {1, x}: // capture tup[1] into 'x' when tup[0] == 1 > default: // same as {...} > } > > > What's quite important here is the "final switch". D has to make sure you are considering all possible cases. > > - - - - - - - - - - - - > > I suggest to leave this to the second stage, and remove it from this proposal: > > auto tup = {1, "hi", 3.14, [1,2,3]}; > if (auto {1, "hi", ...} = tup) {} > > - - - - - - - - - - - - > > "will" is written badly: > > > // If the first element of coord is equal to 1 (== x), 'then' statement > wil be evaluated. > Will fix. > - - - - - - - - - - - - > > I think this is the third thing to leave to the second stage: > > int x = 1; > if (auto {$x, y} = coord) { ... } > > - - - - - - - - - - - - > > This is nice: > > if (auto {x, y} = coord[]) {} // same, explicitly expands fields > > - - - - - - - - - - - - > > This is handy and it's vaguely present in Python3, but I suggest to leave this (4th thing) to the second stage: > > if (auto {num, msg, ...} = tup) {} // ok, `...` matches to > zero-elements. > Kenji Hara |
March 29, 2013 Re: DIP32: Uniform tuple syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to kenji hara | kenji hara: > For tuple values with named fields, we need more thoughts about semantics. > > alias MyPair = typeof({1, "hi"}); > alias MyRecord = typeof({count:1, msg:"hi"}); > static assert(is(MyPair == MyRecord)); // true or false? > static assert(is(MyPair : MyRecord)); // true or false? > static assert(is(MyRecord : MyPair)); // true or false? > alias MyStudent = typeof({num:1, name:"John"}); > static assert(is(MyRecord == MyStudent)); // true or false? One solution: http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29 {count:1, "hi"} and {1, msg:"hi"} are invariant. {count:1, msg:"hi"}, {count:1, "hi"} and {1, msg:"hi"} are covariant to {1, "hi"}. But I think it's better to leave this to the Stage2. Bye, bearophile |
March 29, 2013 Re: DIP32: Uniform tuple syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr Attachments:
| 2013/3/29 Timon Gehr <timon.gehr@gmx.ch> > Looks quite nice. I especially like the {a, b} => ... thing. > > I think, however, that there are a handful serious flaws that need to be addressed: > > 0 "Inside tuple literal, ; never appears." > {{;}} // a tuple not matching your specification > It will be parsed as: { // tuple braces {;} // function literal braces } > {{if(foo()){}}} // a non-tuple matching your specification > { // tuple braces { // function literal braces if (foo()){} // "if" always appears in statement scope } } > 1 "Note: Cannot swap values by tuple assignment." > IMO a no-go. The syntax is too accessible to introduce this kind of > pitfall. > Allowing value swap in tuple assignment will make language complex. I can't agree with it. > 2 "// Error: cannnot use $ inside a function literal" > That's a DMD-ism presumably stemming from laziness during "fixing" of > an ICE/wrong code bug or something. I'd hate to carry this over to > the spec. Don't rely on it. The disambiguation is arbitrary, but may > be necessary. (It's not like it is a case actually occurring in real > code.) > > 3 Unpacking / pattern matching is underspecified. > - Do patterns nest? > I think it should be allowed. > - Which right-hand sides are allowed with which semantics? > Whether it is a pattern or a tuple-literal, is distinguished by their appeared locations. > - Which left-hand sides are allowed with which semantics? > eg, what about: > ref int foo() { ... } > { foo(), foo() } = {1, 2}; > It will be lowered to: // { foo(), foo() } = {1, 2}; foo() = 1; foo() = 2; > 4 There is no way to capture the part matched by "..." > I think this should be allowed. auto {x, r...} = tup; // Lowered to: // auto x = tup[0]; // auto r = tup[1..$] `...` is very consistent token for this purpose. template X(T...) {} alias x = X!(int, long); // T captures {int, long} > 5 .expand (or similar) property is missing. > Use tup[]. It is already exists. > 6 Relation to {a: 2, b: 3}-style struct literals not explained. > I am skeptical of the necessity of tuple literal with named fields. 7 Tuple unpacking for template parameters not mentioned. > > > Is there a migration path for Phobos tuples planned? > > Eg. template Tuple(T...){ alias Tuple = {T}; } > (field spec parsing left out for illustration) > Kenji Hara |
March 29, 2013 Re: DIP32: Uniform tuple syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to kenji hara | On 03/29/2013 04:32 PM, kenji hara wrote: > 2013/3/29 Timon Gehr <timon.gehr@gmx.ch <mailto:timon.gehr@gmx.ch>> > > Looks quite nice. I especially like the {a, b} => ... thing. > > I think, however, that there are a handful serious flaws that need > to be addressed: > > 0 "Inside tuple literal, ; never appears." > {{;}} // a tuple not matching your specification > > > It will be parsed as: > { // tuple braces It contains ';', therefore the DIP says it is a function literal brace. > {;} // function literal braces > } > > {{if(foo()){}}} // a non-tuple matching your specification > > > { // tuple braces > { // function literal braces There is no ';', therefore the DIP says it is a tuple brace. > if (foo()){} // "if" always appears in statement scope > } > } > I know how it _should_ be. The DIP contradicts what you say. > 1 "Note: Cannot swap values by tuple assignment." > IMO a no-go. The syntax is too accessible to introduce this kind of > pitfall. > > > Allowing value swap in tuple assignment will make language complex. I > can't agree with it. > Quite obviously it is the other way round. There will be a never-ending flood of d.D.learn posts on the topic. > 2 "// Error: cannnot use $ inside a function literal" > That's a DMD-ism presumably stemming from laziness during "fixing" of > an ICE/wrong code bug or something. I'd hate to carry this over to > the spec. Don't rely on it. The disambiguation is arbitrary, but may > be necessary. (It's not like it is a case actually occurring in real > code.) > > 3 Unpacking / pattern matching is underspecified. > - Do patterns nest? > > > I think it should be allowed. > ok. > - Which right-hand sides are allowed with which semantics? > > > Whether it is a pattern or a tuple-literal, is distinguished by their > appeared locations. > Obviously, but this statement is not related to my question. Valid right-hand sides seem to be at least tuples and expanded tuples (sequences). Anything else? > - Which left-hand sides are allowed with which semantics? > eg, what about: > ref int foo() { ... } > { foo(), foo() } = {1, 2}; > > > It will be lowered to: > // { foo(), foo() } = {1, 2}; > foo() = 1; > foo() = 2; > ok. > 4 There is no way to capture the part matched by "..." > > > I think this should be allowed. > > auto {x, r...} = tup; > // Lowered to: > // auto x = tup[0]; > // auto r = tup[1..$] > > `...` is very consistent token for this purpose. > Questionable. > template X(T...) {} > alias x = X!(int, long); // T captures {int, long} > Not really. T captures {int, long}.expand. > 5 .expand (or similar) property is missing. > > > Use tup[]. It is already exists. > Slicing obviously shouldn't auto-expand. It's a shortcoming of the Phobos tuple introduced because static slicing cannot be overloaded. > 6 Relation to {a: 2, b: 3}-style struct literals not explained. > > > I am skeptical of the necessity of tuple literal with named fields. > Sure, but you'd at least have to argue in the DIP that the parser can distinguish the two, and how. > 7 Tuple unpacking for template parameters not mentioned. > > > Is there a migration path for Phobos tuples planned? > > Eg. template Tuple(T...){ alias Tuple = {T}; } > (field spec parsing left out for illustration) > >... You have not answered the last two points. |
March 29, 2013 Re: DIP32: Uniform tuple syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to kenji hara | kenji hara:
>> 5 .expand (or similar) property is missing.
>>
>
> Use tup[]. It is already exists.
You are right, I didn't know/remember about that:
import std.typecons;
void foo(int, int) {}
void main() {
auto t = tuple(1, 2);
foo(t.tupleof);
foo(t[]);
auto t2 = tuple(1, 2, 3);
foo(t2[0 .. 2]);
}
But I don't like that. t2[0 .. 2] should return a new tuple that contains just the first two items. And like every one tuple it's not supposed to auto-unpack. So I think this is a design mistake that should be fixed in the new tuples.
Bye,
bearophile
|
March 29, 2013 Re: DIP32: Uniform tuple syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On 2013-03-29 13:49, Adam D. Ruppe wrote: > My first thought when I saw {} was json. This is getting a little > further away from tuples, but would it be hard to add named fields to > this too like json: > > auto a = {"foo":12, "bar":"twelve"}; > > int a_foo = a.foo; > string a_bar = a[1]; I had a proposal of anonymous structs that is similar to this: http://forum.dlang.org/thread/kfbnuc$1cro$1@digitalmars.com -- /Jacob Carlborg |
March 29, 2013 Re: DIP32: Uniform tuple syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On 2013-03-29 14:26, Timon Gehr wrote: > Remove the quotes and it looks like a struct literal. > > I think if named fields are allowed, it should look as follows: > > auto a = {foo: 12, bar: "twelve"}; I agree. -- /Jacob Carlborg |
March 29, 2013 Re: DIP32: Uniform tuple syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr Attachments:
| 2013/3/30 Timon Gehr <timon.gehr@gmx.ch> > On 03/29/2013 04:32 PM, kenji hara wrote: > >> 2013/3/29 Timon Gehr <timon.gehr@gmx.ch <mailto:timon.gehr@gmx.ch>> >> It will be parsed as: >> { // tuple braces >> > > It contains ';', therefore the DIP says it is a function literal brace. > > {;} // function literal braces >> >> } >> >> {{if(foo()){}}} // a non-tuple matching your specification >> >> >> { // tuple braces >> { // function literal braces >> > > There is no ';', therefore the DIP says it is a tuple brace. > > > if (foo()){} // "if" always appears in statement scope >> } >> } >> >> > I know how it _should_ be. The DIP contradicts what you say. > Sorry my incomplete description and poor English. I'll improve description in DIP. > Allowing value swap in tuple assignment will make language complex. I >> can't agree with it. >> > > Quite obviously it is the other way round. There will be a never-ending flood of d.D.learn posts on the topic. > Yes, I agree with it. But, I won't change my opinion. So I'll stop talking about that. > - Which right-hand sides are allowed with which semantics? >> >> >> Whether it is a pattern or a tuple-literal, is distinguished by their appeared locations. >> > > Obviously, but this statement is not related to my question. > Valid right-hand sides seem to be at least tuples and expanded tuples > (sequences). Anything else? > Sorry I don't understand you question. 4 There is no way to capture the part matched by "..." >> >> >> I think this should be allowed. >> >> auto {x, r...} = tup; >> // Lowered to: >> // auto x = tup[0]; >> // auto r = tup[1..$] >> >> `...` is very consistent token for this purpose. >> > > Questionable. > > template X(T...) {} >> alias x = X!(int, long); // T captures {int, long} >> >> > Not really. T captures {int, long}.expand. > > 5 .expand (or similar) property is missing. >> >> >> Use tup[]. It is already exists. >> > > Slicing obviously shouldn't auto-expand. It's a shortcoming of the Phobos tuple introduced because static slicing cannot be overloaded. > I think it will become reasonable. If you really want re-packing tuple, you can use {tup[0..1]}. It's quite handy. 6 Relation to {a: 2, b: 3}-style struct literals not explained. >> >> >> I am skeptical of the necessity of tuple literal with named fields. >> >> > Sure, but you'd at least have to argue in the DIP that the parser can distinguish the two, and how. > > 7 Tuple unpacking for template parameters not mentioned. >> > Will add description about it. Is there a migration path for Phobos tuples planned? >> >> Eg. template Tuple(T...){ alias Tuple = {T}; } >> (field spec parsing left out for illustration) >> > I have no plan. Kenji Hara |
March 29, 2013 Re: DIP32: Uniform tuple syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to kenji hara | kenji hara:
> I think it will become reasonable. If you really want re-packing tuple, you
> can use {tup[0..1]}. It's quite handy.
This is a bad idea. It is not handy and it introduces a special case. Explicit is better than implicit.
Bye,
bearophile
|
March 29, 2013 Re: DIP32: Uniform tuple syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile Attachments:
| 2013/3/30 bearophile <bearophileHUGS@lycos.com>
> kenji hara:
>
>
> I think it will become reasonable. If you really want re-packing tuple,
>> you
>> can use {tup[0..1]}. It's quite handy.
>>
>
> This is a bad idea. It is not handy and it introduces a special case. Explicit is better than implicit.
>
That is "explicit". In D, opened tuple (currently it's generated from
template parameters, e.g. std.typetuple.TypeTuple) and closed tuple
(currently created by structs with alias tuple_field this; e.g.
std.typecons.Tuple) are distinct. Slice operator always returns opened
tuple.
If tup[0..1] makes closed tuple implicitly, you cannot make new flattened
tuple from other tuples.
auto x = {1,"hi"};
auto y = {[1,2], S(1)};
auto tup1 = {x[], y[]}; // creates {1,"hi", [1,2], S(1)}
auto tup2 = {x, y}; // creates {{1,"hi"}, {[1,2], S(1)}}
Under your semantics, it is impossible.
Kenji Hara.
|
Copyright © 1999-2021 by the D Language Foundation