www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - What is the stance on partial initializers when declaring multiple

reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I ran into this simple C declaration:

float float_x, float_y, float_xb, float_yb;

These need to be explicitly initialized in D, otherwise you either get
crashes or you won't get anything but a blank screen (with regards to
rendering with OpenGL).

Almost instinctively I went for:

float float_x, float_y, float_xb, float_yb = 0.0;

But that's incorrect, only float_yb is zero-initialized, the others
are initialized to NaN (well I predicted that but I was kinda hoping D
would be cool and use a common initializer).

What I'm asking is, are partial initializers useful for people? I'm
not suggesting any changes, but just starting a discussion. It does
look like this could maybe introduce bugs. I think someone might have
mentioned this topic before, but I don't recall.

Here's to a healthy discussion..
Jul 20 2011
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-07-21 08:52, Andrej Mitrovic wrote:
 I ran into this simple C declaration:

 float float_x, float_y, float_xb, float_yb;

 These need to be explicitly initialized in D, otherwise you either get
 crashes or you won't get anything but a blank screen (with regards to
 rendering with OpenGL).

How about you create a new type, that can be implicitly converted to float and is initialized to 0.0. -- /Jacob Carlborg
Jul 21 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 7/21/11, Jacob Carlborg <doob me.com> wrote:
 How about you create a new type, that can be implicitly converted to
 float and is initialized to 0.0.

Ha, never thought about that! When I think about it, most of the time I want my floats to be 0-initialized.
Jul 21 2011
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message 
news:mailman.1826.1311231133.14074.digitalmars-d puremagic.com...
I ran into this simple C declaration:

 float float_x, float_y, float_xb, float_yb;

 These need to be explicitly initialized in D, otherwise you either get
 crashes or you won't get anything but a blank screen (with regards to
 rendering with OpenGL).

 Almost instinctively I went for:

 float float_x, float_y, float_xb, float_yb = 0.0;

 But that's incorrect, only float_yb is zero-initialized, the others
 are initialized to NaN (well I predicted that but I was kinda hoping D
 would be cool and use a common initializer).

 What I'm asking is, are partial initializers useful for people? I'm
 not suggesting any changes, but just starting a discussion. It does
 look like this could maybe introduce bugs. I think someone might have
 mentioned this topic before, but I don't recall.

 Here's to a healthy discussion..

It's an interesting point. I find that I rarely declare more than one variable in a single statement. But if I were to do so, then most likely they would be such similar variables that I likely would want them inited to the same value. Can't think of a good syntax for it though. "float a, b, c = 0.0;" definitely makes it look like you're only trying init 'c'. But this is an interesting inconsistency between assignments and initializations. I mean, it's trivial to *assign* multiple variables to the same value: a = b = c = 0.0; *Normally* the only syntactical difference between assignment and initialization is whether or not "x=y;" is preceeded by a type. But with multiple assignments as above, there's no initialization equivalent to that. Crazy, nutty, wacky idea... float (a, b, c) = 0.0; ...?
Jul 21 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Nick Sabalausky:

 Crazy, nutty, wacky idea...
 
 float (a, b, c) = 0.0;

I'd like some syntax sugar for tuples in D (especially for their unpacking), that syntax goes against one of the most natural ways to define tuples. So it's not a good idea. Bye, bearophile
Jul 21 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/21/11 6:44 PM, Simen Kjaeraas wrote:
 On Thu, 21 Jul 2011 23:40:08 +0200, bearophile
 <bearophileHUGS lycos.com> wrote:

 Nick Sabalausky:

 Crazy, nutty, wacky idea...

 float (a, b, c) = 0.0;

I'd like some syntax sugar for tuples in D (especially for their unpacking), that syntax goes against one of the most natural ways to define tuples. So it's not a good idea.

It is highly unlikely that D will ever adopt that syntax for tuples, due to the previously much-discussed comma operator (which, while uncommon, is useful at times). I believe the syntax that came out on top in earlier discussions was the upended hamburger bun, or banana syntax: (| float f, string s |) foo = (| 1.2, "Eh, whut?" |);

Here's a crazy idea: auto foo = tuple(1.2, "Eh, whut?"); Andrei
Jul 21 2011
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/21/11 7:06 PM, Jonathan M Davis wrote:
 On 2011-07-21 16:54, Andrei Alexandrescu wrote:
 On 7/21/11 6:44 PM, Simen Kjaeraas wrote:
 On Thu, 21 Jul 2011 23:40:08 +0200, bearophile

 <bearophileHUGS lycos.com>  wrote:
 Nick Sabalausky:
 Crazy, nutty, wacky idea...

 float (a, b, c) = 0.0;

I'd like some syntax sugar for tuples in D (especially for their unpacking), that syntax goes against one of the most natural ways to define tuples. So it's not a good idea.

It is highly unlikely that D will ever adopt that syntax for tuples, due to the previously much-discussed comma operator (which, while uncommon, is useful at times). I believe the syntax that came out on top in earlier discussions was the upended hamburger bun, or banana syntax: (| float f, string s |) foo = (| 1.2, "Eh, whut?" |);

Here's a crazy idea: auto foo = tuple(1.2, "Eh, whut?");

Is this particular case, a built-in syntax buys you nothing, as you demonstrate. I think that the case that Bearophile is always looking for is something like this: int i; float f; (i, f) = tuple(5, 2.2);

scatter(tuple(5, 2.2), i, f); The more difficult construct is: auto (i, f) = tuple(5, 2.2); Walter and I discussed a language change to allow that. Andrei
Jul 21 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/22/11 4:43 AM, kenji hara wrote:
 2011/7/22 Andrei Alexandrescu<SeeWebsiteForEmail erdani.org>:
 I have posted a pull request for expanding alias this tuples somewhere.
 https://github.com/D-Programming-Language/dmd/pull/74

Great! I made a comment on http://d.puremagic.com/issues/show_bug.cgi?id=2779, please let me know if you agree. Fixing http://d.puremagic.com/issues/show_bug.cgi?id=2781 seems fine as there's no ambiguity there.
 I think that this patch will make conversion seamlessly from built-in
 tuple to library tuple.

 auto (i, f) = tuple(5, 2.2);
 Walter and I discussed a language change to allow that.

I'd like to make patch supporting it.

Sounds great. The way Walter and I wanted to spec that would be as a simple syntactic rewrite. This construct: auto (a1, a2, ..., aN) = x; is expanded mechanically to: static assert(x.length == N, "Too many elements in definition"); auto a1 = x[0]; auto a2 = x[1]; ... auto aN = x[N-1]; This ensures that the feature works with statically-sized arrays and std.Tuple, but also with other types that define the required operations. There's no special casing of library artifacts. If x is an expression, it must be evaluated only once. Let's discuss things here and hear from Walter before you embark on doing this. Andrei
Jul 22 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei:

 Sounds great. The way Walter and I wanted to spec that would be as a 
 simple syntactic rewrite. This construct:
 
 auto (a1, a2, ..., aN) = x;
 
 is expanded mechanically to:
 
 static assert(x.length == N, "Too many elements in definition");
 auto a1 = x[0];
 auto a2 = x[1];
 ...
 auto aN = x[N-1];
 
 This ensures that the feature works with statically-sized arrays and 
 std.Tuple, but also with other types that define the required 
 operations. There's no special casing of library artifacts.
 
 If x is an expression, it must be evaluated only once.
 
 Let's discuss things here and hear from Walter before you embark on 
 doing this.

I have partially lost my grasp on this thread, but this seems what I was asking for. Plus making the syntax work for fixed sized arrays too (and similar user defined types) is good. I sometimes use 2-array or 3-array to return data by value when they are of the same type. Two questions: is typed unpacking too supported? (int a1, float a2, auto a3) = sometuple; Is unpaking inside foreach too supposed to work? This is quite useful: auto somepairs = [tuple(1, "foo"), tuple(10, "bar")]; foreach ((x, name); somepairs) {} ----------- In Haskell you are allowed to call a function with a tuple, and give a local name to the tuple items: somefunction (item1, item2) and to optionally give a name to the whole tuple too: somefunction tuplename (item1, item2) This is sometimes handy, but I think it's currently overkill in D (and it's an additive change). Bye, bearophile
Jul 22 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/22/11 12:32 PM, bearophile wrote:
 Two questions: is typed unpacking too supported?
 (int a1, float a2, auto a3) = sometuple;

The particular rule I suggested does not allow that.
 Is unpaking inside foreach too supposed to work? This is quite useful:
 auto somepairs = [tuple(1, "foo"), tuple(10, "bar")];
 foreach ((x, name); somepairs) {}

This is a bit risky as foreach (x, name; somepairs) would mean something completely different. Andrei
Jul 22 2011
parent bearophile < bearophileHUGS lycos.com> writes:
Andrei:

 Is unpaking inside foreach too supposed to work? This is quite useful:
 auto somepairs = [tuple(1, "foo"), tuple(10, "bar")];
 foreach ((x, name); somepairs) {}

This is a bit risky as foreach (x, name; somepairs) would mean something completely different.

That's unfortunate. foreach(index,item;somearray) was a handy shortcut designed not thinking enough about its wider consequences :-( In Python iterables yield one item, and you are allowed to unpack items if they are composed by more than one item, and to use enumerate() to yield on (index,item) 2-tuples. Removing the optional index from iterating on both arrays and associative arrays (so you need to use something like enumerate() if you want array indexes too, and a AA.byPairs() method if you want key-value 2-tuples of AAs) probably isn't an option because it breaks too much D code. This looks a bit less bug-prone: foreach (tuple(x, name); somepairs) {} ------------------ A third place where tuple unpacking is handy is in switch statements. Supporting switching on structs allows to switch on tuples too. If you allow tuple unpacking syntax here too, you get a poor's man pattern matching, that despite being simple is probably useful. switch (sometuple) { case (0, y): ... case (x, 0): ... case (x, y): ... // no default needed, this catches all other cases } (Note: both AA.byPairs() and switch on structs are useful even if they don't get any special support for tuples.) Bye, bearophile
Jul 22 2011
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/21/11 7:27 PM, Simen Kjaeraas wrote:
 On Fri, 22 Jul 2011 02:06:48 +0200, Jonathan M Davis
 <jmdavisProg gmx.com> wrote:

 On 2011-07-21 16:54, Andrei Alexandrescu wrote:
 On 7/21/11 6:44 PM, Simen Kjaeraas wrote:
 On Thu, 21 Jul 2011 23:40:08 +0200, bearophile

 <bearophileHUGS lycos.com> wrote:
 Nick Sabalausky:
 Crazy, nutty, wacky idea...

 float (a, b, c) = 0.0;

I'd like some syntax sugar for tuples in D (especially for their unpacking), that syntax goes against one of the most natural ways to define tuples. So it's not a good idea.

It is highly unlikely that D will ever adopt that syntax for tuples, due to the previously much-discussed comma operator (which, while uncommon, is useful at times). I believe the syntax that came out on top in earlier discussions was the upended hamburger bun, or banana syntax: (| float f, string s |) foo = (| 1.2, "Eh, whut?" |);

Here's a crazy idea: auto foo = tuple(1.2, "Eh, whut?");

Is this particular case, a built-in syntax buys you nothing, as you demonstrate. I think that the case that Bearophile is always looking for is something like this: int i; float f; (i, f) = tuple(5, 2.2);

Ten minutes of hacking later: /////////////////////////////////////// import std.typecons; import std.typetuple; template getType( alias A ) { alias typeof( A ) getType; } template getType( T ) { alias T getType; } property auto unpack( T... )( Tuple!( staticMap!( getType, T ) ) args ) { foreach ( i, e; T ) { T[i] = args.field[i]; } } unittest { int n; string s; unpack!(n,s) = tuple(4, "O HAI"); assert(n == 4); assert(s == "O HAI"); } //////////////////////////////////////////// Please note that this is not heavily tested, and will likely fail under some (read: many) circumstances. Adding some more magic, one could probably do things like: int n; unpack!(UNUSED, n, UNUSED) = tuple("foo", 4, "bar");

A similar method was proposed by a Phobos contributor (Shoo I think?) at a point under a different name. I rejected it because it was difficult to make safe (it saved the addresses of its arguments). Yours is safe though, but doesn't allow expressions e.g. unpack!(a[0], a[1]) = tuple(1, 1); It's an interesting idea though. Andrei
Jul 21 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Well I don't know about special syntaxes.

What I might have overheard was that if you do initialize in the
declaration, the compiler might request that you specify initializers
for all the variables. In other words:

float x, y, z = 0.0;  // error
float x = 0.0, y = 0.0, z = 0.0; // ok

But I don't know, this could be waay too intrusive from a low-level
language. I think I saw someone mention they would like partial
initializers to go away. I'm so-so with the idea, it could be too much
trouble for any gain.
Jul 21 2011
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Thu, 21 Jul 2011 23:34:59 +0200, Andrej Mitrovic  
<andrej.mitrovich gmail.com> wrote:

 Well I don't know about special syntaxes.

 What I might have overheard was that if you do initialize in the
 declaration, the compiler might request that you specify initializers
 for all the variables. In other words:

 float x, y, z = 0.0;  // error
 float x = 0.0, y = 0.0, z = 0.0; // ok

 But I don't know, this could be waay too intrusive from a low-level
 language. I think I saw someone mention they would like partial
 initializers to go away. I'm so-so with the idea, it could be too much
 trouble for any gain.

I like this. It might not be a common bug, and D has reasonable enough defaults that it's not unlikely you will notice the problem soon, but it has a very simple workaround (declare variables on more than one line) and gives a very clear indication of what might be wrong. Votes++; -- Simen
Jul 21 2011
prev sibling next sibling parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Thu, 21 Jul 2011 23:40:08 +0200, bearophile <bearophileHUGS lycos.com>  
wrote:

 Nick Sabalausky:

 Crazy, nutty, wacky idea...

 float (a, b, c) = 0.0;

I'd like some syntax sugar for tuples in D (especially for their unpacking), that syntax goes against one of the most natural ways to define tuples. So it's not a good idea.

It is highly unlikely that D will ever adopt that syntax for tuples, due to the previously much-discussed comma operator (which, while uncommon, is useful at times). I believe the syntax that came out on top in earlier discussions was the upended hamburger bun, or banana syntax: (| float f, string s |) foo = (| 1.2, "Eh, whut?" |); (do note that I enjoy a wide variety of toppings on my burgers :p) Even if the comma operator were removed and that syntax used for tuples, Nick's suggested syntax would not cause ambiguities. -- Simen
Jul 21 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Simen Kjaeraas:

 I believe the syntax that came out on
 top in earlier discussions was the upended hamburger bun, or banana
 syntax:
 
 (| float f, string s |) foo = (| 1.2, "Eh, whut?" |);

I was the one to suggest this syntax. Andrei told me this is named banana syntax. There are also alternatives: (| auto f, auto s |) foo = (| 1.2, "Eh, whut?" |); auto (| f, s |) foo = (| 1.2, "Eh, whut?" |);
 Even if the comma operator were removed and that syntax used for
 tuples, Nick's suggested syntax would not cause ambiguities.

I like the banana syntax, but I think some people don't like it. So as second choice there is a Python-style tuple syntax. ----------------- Andrei:
 Here's a crazy idea:
 
 auto foo = tuple(1.2, "Eh, whut?");

This was in my original answer:
(especially for their unpacking),<

The main point of having some tuple syntax sugar is to allow a good enough unpacking. Currently it's not good enough for a language as D that wants to be functional too. Functional languages use tuples often. If you are also able to improve the literals too, then it's even better. A return tuple is better than ref/out arguments, as used in C/C++ languages. It's simpler to read because it's easy to see it's the result of a function. Even Go language, that is otherwise quite minimal, has multiple return values. An example usage: http://rosettacode.org/wiki/Sokoban#D The C++0x version: vector<vector<char>> temp, cur = get<0>(open.front()); string cSol = get<1>(open.front()); int x = get<2>(open.front()); int y = get<3>(open.front()); open.pop(); D2 versione with Tuple: auto item = open.pop(); CTable cur = item[0]; string cSol = item[1]; const int x = item[2]; const int y = item[3]; Python version: cur, csol, x, y = open.popleft() One possible D syntax: const (|cur, cSol, x, y|) = open.pop(); Some tuple unpacking syntax in D is useful in D. There are other useful purposes, like unpacking in foreach: foreach ((|x, y|); zip([1, 2, 3], "abc") {} Python3 shows more syntax, to unpack only the first items of a tuple, but this is less important than a basic unpacking syntax: foo(): return 1, 2, 3, 4 a, b, *somemore = foo() Bye, bearophile
Jul 21 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-07-22 11:56, kenji hara wrote:
 I have posted a pull request for library tuple (= alias this tuple)
 unpacking somewhere:
 https://github.com/D-Programming-Language/dmd/pull/74
 (Test code) https://github.com/D-Programming-Language/dmd/pull/74/files#L7R130

 This patch allows unpacking tuple following places:
 - Non-template function arguments
 - Template function arguments
 - StructLiteral arguments
 - Initializer
 - foreach aggregate
 - foreach range.front

 And I think make enhancement patch allowing tuple declaration like follows:
 auto (i, s) = tuple(1, "str");
 TypeTuple!(string, int[]) (s, arr) = TypeTuple!("str", [1, 2]);

 Syntax:
 ("auto" | TupleTypeName) "(" Identifier ["," Identifier ...] ")" "="
 Initializer ";"

 Tuple assignment is already supported in current D like follows:

 import std.typetuple : seq = TypeTuple;
 void main()
 {
    int x, y;
    seq!(x, y) = seq!(1, 2);  // aassign
    assert(x == 1);
    assert(y == 2);
 }

 I think more language support for tuple assignment is not need.

 Kenji Hara

Cool. But it's quite inconsistent that assignment requires "seq" and declaration doesn't. (x, y) = seq!(1, 2); Would it be possible to allow the above syntax? -- /Jacob Carlborg
Jul 22 2011
parent Jacob Carlborg <doob me.com> writes:
On 2011-07-22 15:37, kenji hara wrote:
 2011/7/22 Jacob Carlborg<doob me.com>:
 Cool. But it's quite inconsistent that assignment requires "seq" and
 declaration doesn't.

Yes it is inconsistent, but I think it is not big problem. Because assignment for reusing variables is not good way. It is not 'functional', need 'side-effect', so
 (x, y) = seq!(1, 2);

 Would it be possible to allow the above syntax?

it seems to me that supporting above syntax is not worth changing grammar cost. Kenji Hara

Ok, I see. -- /Jacob Carlborg
Jul 22 2011
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Fri, 22 Jul 2011 01:54:23 +0200, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 7/21/11 6:44 PM, Simen Kjaeraas wrote:
 On Thu, 21 Jul 2011 23:40:08 +0200, bearophile
 <bearophileHUGS lycos.com> wrote:

 Nick Sabalausky:

 Crazy, nutty, wacky idea...

 float (a, b, c) = 0.0;

I'd like some syntax sugar for tuples in D (especially for their unpacking), that syntax goes against one of the most natural ways to define tuples. So it's not a good idea.

It is highly unlikely that D will ever adopt that syntax for tuples, due to the previously much-discussed comma operator (which, while uncommon, is useful at times). I believe the syntax that came out on top in earlier discussions was the upended hamburger bun, or banana syntax: (| float f, string s |) foo = (| 1.2, "Eh, whut?" |);

Here's a crazy idea: auto foo = tuple(1.2, "Eh, whut?");

Ooh, shiny. I bet I could implement that in the language as-is. -- Simen
Jul 21 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-07-21 16:54, Andrei Alexandrescu wrote:
 On 7/21/11 6:44 PM, Simen Kjaeraas wrote:
 On Thu, 21 Jul 2011 23:40:08 +0200, bearophile
 
 <bearophileHUGS lycos.com> wrote:
 Nick Sabalausky:
 Crazy, nutty, wacky idea...
 
 float (a, b, c) = 0.0;

I'd like some syntax sugar for tuples in D (especially for their unpacking), that syntax goes against one of the most natural ways to define tuples. So it's not a good idea.

It is highly unlikely that D will ever adopt that syntax for tuples, due to the previously much-discussed comma operator (which, while uncommon, is useful at times). I believe the syntax that came out on top in earlier discussions was the upended hamburger bun, or banana syntax: (| float f, string s |) foo = (| 1.2, "Eh, whut?" |);

Here's a crazy idea: auto foo = tuple(1.2, "Eh, whut?");

Is this particular case, a built-in syntax buys you nothing, as you demonstrate. I think that the case that Bearophile is always looking for is something like this: int i; float f; (i, f) = tuple(5, 2.2); though that's more useful when the function is something fancier than tuple which just so happens to return a tuple (as opposed to being specifically designed just for creating them). How useful that really is ultimately, I don't know, but it certainly adds something which you can't do without changes to the language itself. Aside from assigning the pieces of a returned tuple to existing local variables like that, I'm not aware of any real gain from adding tuples directly to the language. Our template solution works quite well overall. And whether assigning to existing local variables like above actually makes adding tuples to the language itself worth it is certainly up for debate. But I believe that that's the use case that Bearophile is particularly interested in. - Jonathan M Davis
Jul 21 2011
prev sibling next sibling parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Fri, 22 Jul 2011 02:06:48 +0200, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On 2011-07-21 16:54, Andrei Alexandrescu wrote:
 On 7/21/11 6:44 PM, Simen Kjaeraas wrote:
 On Thu, 21 Jul 2011 23:40:08 +0200, bearophile

 <bearophileHUGS lycos.com> wrote:
 Nick Sabalausky:
 Crazy, nutty, wacky idea...

 float (a, b, c) = 0.0;

I'd like some syntax sugar for tuples in D (especially for their unpacking), that syntax goes against one of the most natural ways to define tuples. So it's not a good idea.

It is highly unlikely that D will ever adopt that syntax for tuples, due to the previously much-discussed comma operator (which, while uncommon, is useful at times). I believe the syntax that came out on top in earlier discussions was the upended hamburger bun, or banana syntax: (| float f, string s |) foo = (| 1.2, "Eh, whut?" |);

Here's a crazy idea: auto foo = tuple(1.2, "Eh, whut?");

Is this particular case, a built-in syntax buys you nothing, as you demonstrate. I think that the case that Bearophile is always looking for is something like this: int i; float f; (i, f) = tuple(5, 2.2);

Ten minutes of hacking later: /////////////////////////////////////// import std.typecons; import std.typetuple; template getType( alias A ) { alias typeof( A ) getType; } template getType( T ) { alias T getType; } property auto unpack( T... )( Tuple!( staticMap!( getType, T ) ) args ) { foreach ( i, e; T ) { T[i] = args.field[i]; } } unittest { int n; string s; unpack!(n,s) = tuple(4, "O HAI"); assert(n == 4); assert(s == "O HAI"); } //////////////////////////////////////////// Please note that this is not heavily tested, and will likely fail under some (read: many) circumstances. Adding some more magic, one could probably do things like: int n; unpack!(UNUSED, n, UNUSED) = tuple("foo", 4, "bar"); -- Simen
Jul 21 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Simen Kjaeraas:

      int n;
      string s;
 
      unpack!(n,s) = tuple(4, "O HAI");

See my other answer. Beside being long and ugly, it doesn't define the types too. And you can't use it in foreach. In my opinion a tuple syntax is more important than having built-in associative arrays. This means I'd like to remove D built-in associative arrays and replace them with built-in tuples. Tuples are more commonly useful than associative arrays, and in D there are enough ways to design a good enough library-defined AA. The only problem are AA literals, but a bit of sugar can solve this problem too. In Scala associative arrays look good enough and they are fully in the library. There is just a -> built-in syntax to define 2-tuples, used to create AA literals. Bye, bearophile
Jul 21 2011
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-07-22 03:29, Simen Kjaeraas wrote:
 I agree that a shorter syntax for 2-tuples could be beneficial, and
 certainly may make more people use it (also, the -> arrow is not
 taken yet):

 auto foo = AA([
 "a" -> 1,
 "b" -> 19,
 "c" -> -3,
 ]);

Now that is a syntax I would like to see in D. This would be even better: auto foo = "a" -> 1, "b" -> 19, "c" -> -3; -- /Jacob Carlborg
Jul 22 2011
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-07-22 03:29, Simen Kjaeraas wrote:
 On Fri, 22 Jul 2011 02:50:52 +0200, bearophile
 <bearophileHUGS lycos.com> wrote:

 Simen Kjaeraas:

 int n;
 string s;

 unpack!(n,s) = tuple(4, "O HAI");

See my other answer. Beside being long and ugly, it doesn't define the types too. And you can't use it in foreach.

Yeah, I can absolutely see that there are places where this could not reasonably be used. Initializing const and immutable data definitely is one. And being able to use it in a foreach would be very nice. Something that might take us part of the way, at least, would be for alias this to support typetuples. Thus: struct Tuple(T...) { T fields; alias fields this; } void foo(int n, string s) {} foo(tuple(3, "bar")); would work. Foreach would direcly benefit from this: foreach (x, y; zip([1,2,3], "abc")) {} // Look ma! No bananas!

That would be really nice. -- /Jacob Carlborg
Jul 22 2011
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
bearophile wrote:
 In Scala associative arrays look good enough and they are fully in the
 library. There is just a -> built-in syntax to define 2-tuples, used to
 create AA literals.

Actually -> is not built-in, but in the library too. As a consequence, -> has the same precedence as + and -. 1*1 -> 2*2 works, but 1+1 -> (2+2) requires parentheses. Cheers, -Timon
Jul 22 2011
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Fri, 22 Jul 2011 02:50:52 +0200, bearophile <bearophileHUGS lycos.com>  
wrote:

 Simen Kjaeraas:

      int n;
      string s;

      unpack!(n,s) = tuple(4, "O HAI");

See my other answer. Beside being long and ugly, it doesn't define the types too. And you can't use it in foreach.

Yeah, I can absolutely see that there are places where this could not reasonably be used. Initializing const and immutable data definitely is one. And being able to use it in a foreach would be very nice. Something that might take us part of the way, at least, would be for alias this to support typetuples. Thus: struct Tuple(T...) { T fields; alias fields this; } void foo(int n, string s) {} foo(tuple(3, "bar")); would work. Foreach would direcly benefit from this: foreach (x, y; zip([1,2,3], "abc")) {} // Look ma! No bananas!
 In my opinion a tuple syntax is more important than having built-in  
 associative arrays. This means I'd like to remove D built-in associative  
 arrays and replace them with built-in tuples. Tuples are more commonly  
 useful than associative arrays, and in D there are enough ways to design  
 a good enough library-defined AA.

 The only problem are AA literals, but a bit of sugar can solve this  
 problem too. In Scala associative arrays look good enough and they are  
 fully in the library. There is just a -> built-in syntax to define  
 2-tuples, used to create AA literals.

this could work today, given a proper constructor: int[string] foo = [ tuple("a", 1), tuple("b", 19), tuple("c", -3), ]; or: auto foo = AA([ tuple("a", 1), tuple("b", 19), tuple("c", -3), ]); Or, if we go bananas: int[string] foo = [ (|"a", 1|), (|"b", 19|), (|"c", -3|), ]; I agree that a shorter syntax for 2-tuples could be beneficial, and certainly may make more people use it (also, the -> arrow is not taken yet): auto foo = AA([ "a" -> 1, "b" -> 19, "c" -> -3, ]); As for actual typing, 5 characters are saved per line for the tersest version, and only 3 with bananas. Not enough that I'm convinced by that argument alone, but the more natural feel of the -> syntax has me intrigued. (these numbers would also be somewhat different if I weren't nazi about my spaces) This is not just about what can be done, but also how to make users actually use the features. I believe, but do not know, that many users would feel more comfortable with the latter syntax than the one saying tuple all the time. -- Simen
Jul 21 2011
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
In current D, following code is valid.

import std.typetuple : seq = TypeTuple;
void main()
{
  int x, y;
  seq!(x, y) = seq!(1, 2);  // assign
  assert(x == 1);
  assert(y == 2);
}

Kenji Hara

2011/7/22 Jonathan M Davis <jmdavisProg gmx.com>:
 On 2011-07-21 16:54, Andrei Alexandrescu wrote:
 On 7/21/11 6:44 PM, Simen Kjaeraas wrote:
 On Thu, 21 Jul 2011 23:40:08 +0200, bearophile

 <bearophileHUGS lycos.com> wrote:
 Nick Sabalausky:
 Crazy, nutty, wacky idea...

 float (a, b, c) = 0.0;

I'd like some syntax sugar for tuples in D (especially for their unpacking), that syntax goes against one of the most natural ways to define tuples. So it's not a good idea.

It is highly unlikely that D will ever adopt that syntax for tuples, due to the previously much-discussed comma operator (which, while uncommon, is useful at times). I believe the syntax that came out on top in earlier discussions was the upended hamburger bun, or banana syntax: (| float f, string s |) foo = (| 1.2, "Eh, whut?" |);

Here's a crazy idea: auto foo = tuple(1.2, "Eh, whut?");

Is this particular case, a built-in syntax buys you nothing, as you demonstrate. I think that the case that Bearophile is always looking for is something like this: int i; float f; (i, f) = tuple(5, 2.2); though that's more useful when the function is something fancier than tuple which just so happens to return a tuple (as opposed to being specifically designed just for creating them). How useful that really is ultimately, I don't know, but it certainly adds something which you can't do without changes to the language itself. Aside from assigning the pieces of a returned tuple to existing local variables like that, I'm not aware of any real gain from adding tuples directly to the language. Our template solution works quite well overall. And whether assigning to existing local variables like above actually makes adding tuples to the language itself worth it is certainly up for debate. But I believe that that's the use case that Bearophile is particularly interested in. - Jonathan M Davis

Jul 22 2011
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
2011/7/22 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:
 On 7/21/11 7:06 PM, Jonathan M Davis wrote:
 On 2011-07-21 16:54, Andrei Alexandrescu wrote:
 On 7/21/11 6:44 PM, Simen Kjaeraas wrote:
 On Thu, 21 Jul 2011 23:40:08 +0200, bearophile

 <bearophileHUGS lycos.com> =A0wrote:
 Nick Sabalausky:
 Crazy, nutty, wacky idea...

 float (a, b, c) =3D 0.0;

I'd like some syntax sugar for tuples in D (especially for their unpacking), that syntax goes against one of the most natural ways to define tuples. So it's not a good idea.

It is highly unlikely that D will ever adopt that syntax for tuples, due to the previously much-discussed comma operator (which, while uncommon, is useful at times). I believe the syntax that came out on top in earlier discussions was the upended hamburger bun, or banana syntax: (| float f, string s |) foo =3D (| 1.2, "Eh, whut?" |);

Here's a crazy idea: auto foo =3D tuple(1.2, "Eh, whut?");

Is this particular case, a built-in syntax buys you nothing, as you demonstrate. I think that the case that Bearophile is always looking for is something like this: int i; float f; (i, f) =3D tuple(5, 2.2);

scatter(tuple(5, 2.2), i, f); The more difficult construct is: auto (i, f) =3D tuple(5, 2.2); Walter and I discussed a language change to allow that. Andrei

I have posted a pull request for expanding alias this tuples somewhere. https://github.com/D-Programming-Language/dmd/pull/74 I think that this patch will make conversion seamlessly from built-in tuple to library tuple.
 auto (i, f) =3D tuple(5, 2.2);
 Walter and I discussed a language change to allow that.

I'd like to make patch supporting it. Kenji Hara
Jul 22 2011
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
I have posted a pull request for library tuple (=3D alias this tuple)
unpacking somewhere:
https://github.com/D-Programming-Language/dmd/pull/74
(Test code) https://github.com/D-Programming-Language/dmd/pull/74/files#L7R=
130

This patch allows unpacking tuple following places:
- Non-template function arguments
- Template function arguments
- StructLiteral arguments
- Initializer
- foreach aggregate
- foreach range.front

And I think make enhancement patch allowing tuple declaration like follows:
auto (i, s) =3D tuple(1, "str");
TypeTuple!(string, int[]) (s, arr) =3D TypeTuple!("str", [1, 2]);

Syntax:
("auto" | TupleTypeName) "(" Identifier ["," Identifier ...] ")" "=3D"
Initializer ";"

Tuple assignment is already supported in current D like follows:

import std.typetuple : seq =3D TypeTuple;
void main()
{
  int x, y;
  seq!(x, y) =3D seq!(1, 2);  // aassign
  assert(x =3D=3D 1);
  assert(y =3D=3D 2);
}

I think more language support for tuple assignment is not need.

Kenji Hara

2011/7/22 bearophile <bearophileHUGS lycos.com>:
 Simen Kjaeraas:

 I believe the syntax that came out on
 top in earlier discussions was the upended hamburger bun, or banana
 syntax:

 (| float f, string s |) foo =3D (| 1.2, "Eh, whut?" |);

I was the one to suggest this syntax. Andrei told me this is named banana=

 There are also alternatives:
 (| auto f, auto s |) foo =3D (| 1.2, "Eh, whut?" |);
 auto (| f, s |) foo =3D (| 1.2, "Eh, whut?" |);


 Even if the comma operator were removed and that syntax used for
 tuples, Nick's suggested syntax would not cause ambiguities.

I like the banana syntax, but I think some people don't like it. So as se=

 -----------------

 Andrei:

 Here's a crazy idea:

 auto foo =3D tuple(1.2, "Eh, whut?");

This was in my original answer:
(especially for their unpacking),<

The main point of having some tuple syntax sugar is to allow a good enoug=

to be functional too. Functional languages use tuples often.
 If you are also able to improve the literals too, then it's even better.

 A return tuple is better than ref/out arguments, as used in C/C++ languag=

tion. Even Go language, that is otherwise quite minimal, has multiple retur= n values.
 An example usage:
 http://rosettacode.org/wiki/Sokoban#D


 The C++0x version:

 vector<vector<char>> temp, cur =3D get<0>(open.front());
 string cSol =3D get<1>(open.front());
 int x =3D get<2>(open.front());
 int y =3D get<3>(open.front());
 open.pop();


 D2 versione with Tuple:

 auto item =3D open.pop();
 CTable cur =3D item[0];
 string cSol =3D item[1];
 const int x =3D item[2];
 const int y =3D item[3];


 Python version:

 cur, csol, x, y =3D open.popleft()


 One possible D syntax:

 const (|cur, cSol, x, y|) =3D open.pop();

 Some tuple unpacking syntax in D is useful in D.
 There are other useful purposes, like unpacking in foreach:

 foreach ((|x, y|); zip([1, 2, 3], "abc") {}


 Python3 shows more syntax, to unpack only the first items of a tuple, but=

 foo():
 =A0 =A0return 1, 2, 3, 4
 a, b, *somemore =3D foo()

 Bye,
 bearophile

Jul 22 2011
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
2011/7/22 Jacob Carlborg <doob me.com>:
 Cool. But it's quite inconsistent that assignment requires "seq" and
 declaration doesn't.

Yes it is inconsistent, but I think it is not big problem. Because assignment for reusing variables is not good way. It is not 'functional', need 'side-effect', so
 (x, y) = seq!(1, 2);

 Would it be possible to allow the above syntax?

it seems to me that supporting above syntax is not worth changing grammar cost. Kenji Hara
Jul 22 2011
prev sibling next sibling parent Trass3r <un known.com> writes:
Am 21.07.2011, 21:55 Uhr, schrieb Andrej Mitrovic  
<andrej.mitrovich gmail.com>:

 On 7/21/11, Jacob Carlborg <doob me.com> wrote:
 How about you create a new type, that can be implicitly converted to
 float and is initialized to 0.0.

Ha, never thought about that! When I think about it, most of the time I want my floats to be 0-initialized.

me too!
Jul 22 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday 22 July 2011 15:40:00 Trass3r wrote:
 Am 21.07.2011, 21:55 Uhr, schrieb Andrej Mitrovic
 
 <andrej.mitrovich gmail.com>:
 On 7/21/11, Jacob Carlborg <doob me.com> wrote:
 How about you create a new type, that can be implicitly converted to
 float and is initialized to 0.0.

Ha, never thought about that! When I think about it, most of the time I want my floats to be 0-initialized.

me too!

Well, the idea with default initializers is that they're as close as possible to an invalid value (hence NaN for floats) so that it becomes apparent faster if you screwed up and didn't initialize them before using them. So, that's why floats aren't 0 by default. Integral values wouldn't be 0 either if the integral types had something akin to NaN. - Jonathan M Davis
Jul 22 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 7/22/11, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 Integral values wouldn't be 0 either if the
 integral types had something akin to NaN.

Maybe if you're coming from C or C++ you're used to having to manually initialize everything. I personally don't think the issue is about putting a variable in a known invalid state, but just about putting it in a known state to begin with. And you don't get either of those in C and C++. I think 0 for integrals as a default is a great feature. It is a *known* feature, and it's pretty much what I want in 99% of my code. I only ever have to manually specify initializers in very few places for integrals, which saves me a lot of time. Remember, D cares about usability as much as it cares about memory safety. 0 for integrals is a time-saving feature.
Jul 22 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday 23 July 2011 07:16:07 Andrej Mitrovic wrote:
 On 7/22/11, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 Integral values wouldn't be 0 either if the
 integral types had something akin to NaN.

Maybe if you're coming from C or C++ you're used to having to manually initialize everything. I personally don't think the issue is about putting a variable in a known invalid state, but just about putting it in a known state to begin with. And you don't get either of those in C and C++. I think 0 for integrals as a default is a great feature. It is a *known* feature, and it's pretty much what I want in 99% of my code. I only ever have to manually specify initializers in very few places for integrals, which saves me a lot of time. Remember, D cares about usability as much as it cares about memory safety. 0 for integrals is a time-saving feature.

The values which were chosen for default initialization were specifically chose because they were the closest to an error value that each type has. In the case of integral values, there was no value which was really an error value, so 0 was chosen. Whether you rely on that or consider it good practice to always explicitly initialize variables is up to you. But it's was never really the point to avoid having to initialize variables. The point was to avoid undefined state and to make it as clear as possible what went wrong when you forgot to initialize a variable by making the default value as close to an error value as possible. So, it's perfectly legitimate to rely on the fact that integral values default to 0 and not bother to ever initialize the directly, but avoiding having to directly initialize the variable wasn't really the reason for that language design decision. Regardless, the fact that floating point values _can_ have an error value - NaN - means that you're never going to see 0 become the default value for floating point values even if most people typically initialized their floats to 0 (that and the fact that changing it at this point would break a lot of code). - Jonathan M Davis
Jul 23 2011