www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Declaring Ref Variables Inside Function Calls

reply dsimcha <dsimcha yahoo.com> writes:
At times, like when trying to write a syntactically sweet tuple unpacker, I've
wanted to be able to declare a variable that will be passed by reference to a
function inside the function call.  For example:

void doStuff(out uint num) {  // Could also be ref uint num.
    num = 666;
}

import std.stdio;

void main() {
    doStuff(uint foo);  // Declare foo as uint, passes it to doStuff.
    writeln(foo);  // Prints 666.
}

Is it feasible, at least in principle, to allow this, or would this create
issues with parsing, odd ambiguities that I haven't thought of, etc.?
Mar 30 2009
next sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Tue, 31 Mar 2009 06:46:32 +0400, dsimcha <dsimcha yahoo.com> wrote:

 At times, like when trying to write a syntactically sweet tuple  
 unpacker, I've
 wanted to be able to declare a variable that will be passed by reference  
 to a
 function inside the function call.  For example:

 void doStuff(out uint num) {  // Could also be ref uint num.
     num = 666;
 }

 import std.stdio;

 void main() {
     doStuff(uint foo);  // Declare foo as uint, passes it to doStuff.
     writeln(foo);  // Prints 666.
 }

 Is it feasible, at least in principle, to allow this, or would this  
 create
 issues with parsing, odd ambiguities that I haven't thought of, etc.?

It seems loogically that "foo" should die right after doStuff returns, because its scope is limited to parens. It's also redundant to specify type of foo, it can be deduced from function signature (auto foo?). That said, I don't think there is a need for something like this. Certainly no speedup and little clarity compared to declaring variable right before invoking doStuff.
Mar 30 2009
parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Denis Koroskin (2korden gmail.com)'s article
 On Tue, 31 Mar 2009 06:46:32 +0400, dsimcha <dsimcha yahoo.com> wrote:
 At times, like when trying to write a syntactically sweet tuple
 unpacker, I've
 wanted to be able to declare a variable that will be passed by reference
 to a
 function inside the function call.  For example:

 void doStuff(out uint num) {  // Could also be ref uint num.
     num = 666;
 }

 import std.stdio;

 void main() {
     doStuff(uint foo);  // Declare foo as uint, passes it to doStuff.
     writeln(foo);  // Prints 666.
 }

 Is it feasible, at least in principle, to allow this, or would this
 create
 issues with parsing, odd ambiguities that I haven't thought of, etc.?

because its scope is limited to parens. It's also redundant to specify type of foo, it can be deduced from function signature (auto foo?).

Nothing wrong with auto, but you need to specify something, even if it's just auto, to make it clear that you're declaring a type.
 That said, I don't think there is a need for something like this.
 Certainly no speedup and little clarity compared to declaring variable
 right before invoking doStuff.

Here's an example of where it would be a useful piece of sugar, given an unpack function that I was playing with: // How it works now: uint foo; string bar; unpack(foo, bar) = someFunction(); // vs. how I want it to work: unpack(auto foo, auto bar) = someFunction();
Mar 30 2009
next sibling parent dsimcha <dsimcha yahoo.com> writes:
== Quote from Jarrett Billingsley (jarrett.billingsley gmail.com)'s article
 2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) = someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) = someFunction();

would practically remove the need for out parameters, and would remove the need for this request as well (since that's about the only time you'd need it).

Well, apparently, alias this is getting implemented soon (see Phobos changelog on dsource), which for all practical purposes gives returnable tuples because the Tuple struct in std.typetyple can be made to look exactly like a builtin tuple. I assume you mean automatic unpacking of tuples. Not sure if there's any good reason other than higher priority stuff to implement first why this doesn't already exist.
Mar 31 2009
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jarrett Billingsley wrote:
 2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) = someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) = someFunction();

Cute, but uh, I'd much rather see tuples just be returnable.

They are. Andrei
Mar 31 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 1:32 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) = someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) = someFunction();



template Tuple(T...) { alias T Tuple; } Tuple!(int, float) foo() { return Tuple!(3, 4.5); } foo.d(10): Error: functions cannot return a tuple Unless you're using some prerelease compiler, they are not.

import std.typecons; Tuple!(int, float) foo() { return tuple(2, 4.5); } The addition of the alias this feature and of constructor templates makes std.typecons.Tuple even better. Andrei
Mar 31 2009
next sibling parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Tue, 31 Mar 2009 12:18:21 -0700, Andrei Alexandrescu wrote:

 Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 1:32 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) = someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) = someFunction();



template Tuple(T...) { alias T Tuple; } Tuple!(int, float) foo() { return Tuple!(3, 4.5); } foo.d(10): Error: functions cannot return a tuple Unless you're using some prerelease compiler, they are not.

import std.typecons; Tuple!(int, float) foo() { return tuple(2, 4.5); } The addition of the alias this feature and of constructor templates makes std.typecons.Tuple even better. Andrei

Unfair---std.typecons.Tuple is actually a struct! Well, basically struct is a run-time tuple, anyway. I think that all the buzz around "actual tuple support" boils down to requests for syntax sugar for construction and decomposition of anonymous structs. While typecons.Tuple is sorta OK for construction, things are still pretty ugly on the "decomposition" end.
Mar 31 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Wed, Apr 1, 2009 at 5:03 AM, Sergey Gromov <snake.scaly gmail.com> wrote:
 Tue, 31 Mar 2009 12:18:21 -0700, Andrei Alexandrescu wrote:

 Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 1:32 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) = someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) = someFunction();



{ alias T Tuple; } Tuple!(int, float) foo() { return Tuple!(3, 4.5); } foo.d(10): Error: functions cannot return a tuple Unless you're using some prerelease compiler, they are not.

Tuple!(int, float) foo() { return tuple(2, 4.5); } The addition of the alias this feature and of constructor templates makes std.typecons.Tuple even better. Andrei

Well, basically struct is a run-time tuple, anyway. I think that all the buzz around "actual tuple support" boils down to requests for syntax sugar for construction and decomposition of anonymous structs. While typecons.Tuple is sorta OK for construction, things are still pretty ugly on the "decomposition" end.

Right. In my ideal world I could use tuples like this: (int,float) a;

That sucks. Is int(int, float) a function type or a juxtaposition of two types? Is (A, B) an expression or a type? And so on.
 a = returns_tuple();
 
 a[0] = 2;
 a[1] = 3.4;

That works in my tree already due to alias this.
 (int,float) z = returns_tuple();

Blech.
 (int x, float y) = returns_tuple();

I'd like that too, but what we should have is make any definition an expression.
 auto tup = (2, 3.4);

Belch (sic).
 takes_int_and_float(unpack!(tup));

Meh.
 I think experience with tuples in Python and ML (and probably
 elsewhere -- heck even D) shows that tuples are incredibly useful.  So
 useful that they deserve better syntax than Tuple!(...).

Ehm. Andrei
Mar 31 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Wed, Apr 1, 2009 at 6:16 AM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Wed, Apr 1, 2009 at 5:03 AM, Sergey Gromov <snake.scaly gmail.com>
 wrote:
 Tue, 31 Mar 2009 12:18:21 -0700, Andrei Alexandrescu wrote:

 Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 1:32 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) = someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) = someFunction();



{ alias T Tuple; } Tuple!(int, float) foo() { return Tuple!(3, 4.5); } foo.d(10): Error: functions cannot return a tuple Unless you're using some prerelease compiler, they are not.

Tuple!(int, float) foo() { return tuple(2, 4.5); } The addition of the alias this feature and of constructor templates makes std.typecons.Tuple even better. Andrei

Well, basically struct is a run-time tuple, anyway. I think that all the buzz around "actual tuple support" boils down to requests for syntax sugar for construction and decomposition of anonymous structs. While typecons.Tuple is sorta OK for construction, things are still pretty ugly on the "decomposition" end.

(int,float) a;

types?

I should say that by "in my ideal world" what I meant was "forgetting about all the baggage that D already has for a moment and starting from a more or less clean slate". Things like the useless comma operator. But isn't a juxtaposition of two types a syntax error? So the above would be a function type, not a juxtaposition of two types.
 Is (A, B) an expression or a type? And so on.

How does that differ from asking "Is A an expression or a type?" If A and B are types, then (A,B) is a type.
 (int,float) z = returns_tuple();


Blech to that, but you like Tuple!(int,float) z = returns_tuple(); correct?
 (int x, float y) = returns_tuple();

expression.
 auto tup = (2, 3.4);


Belch to that, but again, you're saying this is great auto tup = Tuple!(2, 3.4); correct? --bb

Yah, sorry for the dismissive comments... what I meant was that the literal you suggested is so ambiguous grammatically, it's a non-improvement compared to just writing Tuple! there. Andrei
Mar 31 2009
parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Tue, 31 Mar 2009 17:54:30 -0700, Andrei Alexandrescu wrote:

 Bill Baxter wrote:
 On Wed, Apr 1, 2009 at 6:16 AM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Wed, Apr 1, 2009 at 5:03 AM, Sergey Gromov <snake.scaly gmail.com>
 wrote:
 Tue, 31 Mar 2009 12:18:21 -0700, Andrei Alexandrescu wrote:

 Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 1:32 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) = someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) = someFunction();



{ alias T Tuple; } Tuple!(int, float) foo() { return Tuple!(3, 4.5); } foo.d(10): Error: functions cannot return a tuple Unless you're using some prerelease compiler, they are not.

Tuple!(int, float) foo() { return tuple(2, 4.5); } The addition of the alias this feature and of constructor templates makes std.typecons.Tuple even better. Andrei

Well, basically struct is a run-time tuple, anyway. I think that all the buzz around "actual tuple support" boils down to requests for syntax sugar for construction and decomposition of anonymous structs. While typecons.Tuple is sorta OK for construction, things are still pretty ugly on the "decomposition" end.

(int,float) a;

types?

I should say that by "in my ideal world" what I meant was "forgetting about all the baggage that D already has for a moment and starting from a more or less clean slate". Things like the useless comma operator. But isn't a juxtaposition of two types a syntax error? So the above would be a function type, not a juxtaposition of two types.
 Is (A, B) an expression or a type? And so on.

How does that differ from asking "Is A an expression or a type?" If A and B are types, then (A,B) is a type.
 (int,float) z = returns_tuple();


Blech to that, but you like Tuple!(int,float) z = returns_tuple(); correct?
 (int x, float y) = returns_tuple();

expression.
 auto tup = (2, 3.4);


Belch to that, but again, you're saying this is great auto tup = Tuple!(2, 3.4); correct? --bb

Yah, sorry for the dismissive comments... what I meant was that the literal you suggested is so ambiguous grammatically, it's a non-improvement compared to just writing Tuple! there.

Comma expression is not ambiguous. It's a comma expression. Renaming it into a tuple constructor expression does not add any ambiguity. Parentheses here are only required to separate the comma expression from an assignment expression which otherwise would become a part of comma expression. Sure there are problems with making tuples first-class, but this is certainly not one of them. I'm putting together a blog post about a possible design of first-class tuples in D. Hope it won't take too long.
Mar 31 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Sergey Gromov wrote:
 Comma expression is not ambiguous.  It's a comma expression.  Renaming
 it into a tuple constructor expression does not add any ambiguity.
 Parentheses here are only required to separate the comma expression from
 an assignment expression which otherwise would become a part of comma
 expression.  Sure there are problems with making tuples first-class, but
 this is certainly not one of them.

I don't understand. So are you suggesting that the comma expression gets sacked?
 I'm putting together a blog post about a possible design of first-class
 tuples in D.  Hope it won't take too long.

What does "first-class" mean? Andrei
Mar 31 2009
parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Tue, 31 Mar 2009 18:38:35 -0700, Andrei Alexandrescu wrote:

 Sergey Gromov wrote:
 Comma expression is not ambiguous.  It's a comma expression.  Renaming
 it into a tuple constructor expression does not add any ambiguity.
 Parentheses here are only required to separate the comma expression from
 an assignment expression which otherwise would become a part of comma
 expression.  Sure there are problems with making tuples first-class, but
 this is certainly not one of them.

I don't understand. So are you suggesting that the comma expression gets sacked?

Now comma expression drops all the results but the last one. You lose nothing by making it keep other results as well. Then you can make it extract the last element as a result of an implicit cast. Disallowing the C-style usage of comma expression is also an option.
 I'm putting together a blog post about a possible design of first-class
 tuples in D.  Hope it won't take too long.

What does "first-class" mean?

First-class values, like, native, with built-in compiler support.
Mar 31 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Sergey Gromov wrote:
 Tue, 31 Mar 2009 18:38:35 -0700, Andrei Alexandrescu wrote:
 
 Sergey Gromov wrote:
 Comma expression is not ambiguous.  It's a comma expression.  Renaming
 it into a tuple constructor expression does not add any ambiguity.
 Parentheses here are only required to separate the comma expression from
 an assignment expression which otherwise would become a part of comma
 expression.  Sure there are problems with making tuples first-class, but
 this is certainly not one of them.

sacked?

Now comma expression drops all the results but the last one. You lose nothing by making it keep other results as well. Then you can make it extract the last element as a result of an implicit cast.

That won't work because you'd paste C code into your D code and it'll compile with different results.
 Disallowing the C-style usage of comma expression is also an option.

Ok.
 I'm putting together a blog post about a possible design of first-class
 tuples in D.  Hope it won't take too long.


First-class values, like, native, with built-in compiler support.

A tuple is a parameterized type, not a value. And first-class doesn't mean with built-in compiler support. Andrei
Mar 31 2009
parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Tue, 31 Mar 2009 18:55:10 -0700, Andrei Alexandrescu wrote:

 Sergey Gromov wrote:
 Tue, 31 Mar 2009 18:38:35 -0700, Andrei Alexandrescu wrote:
 
 Sergey Gromov wrote:
 Comma expression is not ambiguous.  It's a comma expression.  Renaming
 it into a tuple constructor expression does not add any ambiguity.
 Parentheses here are only required to separate the comma expression from
 an assignment expression which otherwise would become a part of comma
 expression.  Sure there are problems with making tuples first-class, but
 this is certainly not one of them.

sacked?

Now comma expression drops all the results but the last one. You lose nothing by making it keep other results as well. Then you can make it extract the last element as a result of an implicit cast.

That won't work because you'd paste C code into your D code and it'll compile with different results.

It should be possible to make the C pattern work as expected. I need to think about this in more detail to be sure.
 I'm putting together a blog post about a possible design of first-class
 tuples in D.  Hope it won't take too long.


First-class values, like, native, with built-in compiler support.

A tuple is a parameterized type, not a value. And first-class doesn't mean with built-in compiler support.

Probably I've mis-used the first-class thing here.
Mar 31 2009
parent Leandro Lucarella <llucax gmail.com> writes:
Sergey Gromov, el  1 de abril a las 06:08 me escribiste:
 I'm putting together a blog post about a possible design of first-class
 tuples in D.  Hope it won't take too long.


First-class values, like, native, with built-in compiler support.

A tuple is a parameterized type, not a value. And first-class doesn't mean with built-in compiler support.

Probably I've mis-used the first-class thing here.

First class object, according to Wikipedia[1], means, among other things, that is "being expressible as an anonymous literal value". Since in D there is no way to define new literals in library code (until macros are implemented, I hope =), the only way to add tuple literals that I know of is adding built-in compiler support. Then assuming, as discussed in this thread, that you'll propose tuples to have literal values in your blog post, I don't think you mis-used the term here =) [1] http://en.wikipedia.org/wiki/First-class_object -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- Are you nervy, irritable, depressed, tired of life. Keep it up. -- Monty Python
Apr 01 2009
prev sibling next sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
Bill Baxter, el  1 de abril a las 05:22 me escribiste:
 Right.  In my ideal world I could use tuples like this:
 
 (int,float) a;
 
 a = returns_tuple();
 
 a[0] = 2;
 a[1] = 3.4;
 
 (int,float) z = returns_tuple();
 
 (int x, float y) = returns_tuple();
 
 auto tup = (2, 3.4);
 
 takes_int_and_float(unpack!(tup));
 
 I think experience with tuples in Python and ML (and probably
 elsewhere -- heck even D) shows that tuples are incredibly useful.  So
 useful that they deserve better syntax than Tuple!(...).

Agree. They should be first class citizen as dynamic arrays or hashes. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ----------------------------------------------------------------------------
Mar 31 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Leandro Lucarella wrote:
 Bill Baxter, el  1 de abril a las 05:22 me escribiste:
 Right.  In my ideal world I could use tuples like this:

 (int,float) a;

 a = returns_tuple();

 a[0] = 2;
 a[1] = 3.4;

 (int,float) z = returns_tuple();

 (int x, float y) = returns_tuple();

 auto tup = (2, 3.4);

 takes_int_and_float(unpack!(tup));

 I think experience with tuples in Python and ML (and probably
 elsewhere -- heck even D) shows that tuples are incredibly useful.  So
 useful that they deserve better syntax than Tuple!(...).

Agree. They should be first class citizen as dynamic arrays or hashes.

Why? Not grokking it. Andrei
Mar 31 2009
parent reply Leandro Lucarella <llucax gmail.com> writes:
Andrei Alexandrescu, el 31 de marzo a las 17:57 me escribiste:
 Leandro Lucarella wrote:
Bill Baxter, el  1 de abril a las 05:22 me escribiste:
Right.  In my ideal world I could use tuples like this:

(int,float) a;

a = returns_tuple();

a[0] = 2;
a[1] = 3.4;

(int,float) z = returns_tuple();

(int x, float y) = returns_tuple();

auto tup = (2, 3.4);

takes_int_and_float(unpack!(tup));

I think experience with tuples in Python and ML (and probably
elsewhere -- heck even D) shows that tuples are incredibly useful.  So
useful that they deserve better syntax than Tuple!(...).


Why? Not grokking it.

It's perfectly explained in this thread why, all I have to say will repeate something already said (the int[] vs. std::vector<int> mostly). Of course you don't seem to agree with those arguments... If they are not 1st citizens you just end up: 1) not using them 2) making your code look like boost, I mean *really* ugly ;) (when what you want to do it's even possible, of course) -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- Every year is getting shorter never seem to find the time. Plans that either come to nought or half a page of scribbled lines. Hanging on in quiet desparation is the English way. The time is gone, the song is over, thought I'd something more to say.
Mar 31 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Leandro Lucarella wrote:
 Andrei Alexandrescu, el 31 de marzo a las 17:57 me escribiste:
 Agree. They should be first class citizen as dynamic arrays or hashes.


It's perfectly explained in this thread why, all I have to say will repeate something already said (the int[] vs. std::vector<int> mostly). Of course you don't seem to agree with those arguments...

Well I don't agree, but maybe there's more arguments that could improve that.
 If they are not 1st citizens you just end up:
 1) not using them
 2) making your code look like boost, I mean *really* ugly ;)
    (when what you want to do it's even possible, of course)
 

Tuple is a 1st citizen language constituent (they have to). It just doesn't have a literal. Say we do invent a literal, e.g.: [: int, float :] mytuple; Does this improve the language over Tuple!(int, float)? I'm not convinced - at all, in fact. Right now Tuple is on equal footing with other templates and whatever introspection we have/will add works/will work on Tuple as it works with other templates. With the extra syntax, we'll then need to add special methods for introspecting a tuple. We'll find ourselves also reserving a keyword "tuple" and positing that [: ... :] is the same as tuple!(...) or some other similarly unpleasant solution. Plus, special syntax contributes to the disconnect between user-defined and built-in. This creates the self-perpetuating trend that if anything is interesting, it should have a literal allocated to it. Instead of that, let's think e.g. of methods to generally make parameterized types look better. Andrei
Mar 31 2009
parent Leandro Lucarella <llucax gmail.com> writes:
Andrei Alexandrescu, el 31 de marzo a las 18:50 me escribiste:
 Leandro Lucarella wrote:
Andrei Alexandrescu, el 31 de marzo a las 17:57 me escribiste:
Agree. They should be first class citizen as dynamic arrays or hashes.


repeate something already said (the int[] vs. std::vector<int> mostly). Of course you don't seem to agree with those arguments...

Well I don't agree, but maybe there's more arguments that could improve that.
If they are not 1st citizens you just end up:
1) not using them
2) making your code look like boost, I mean *really* ugly ;)
   (when what you want to do it's even possible, of course)

Tuple is a 1st citizen language constituent (they have to). It just doesn't have a literal. Say we do invent a literal, e.g.: [: int, float :] mytuple; Does this improve the language over Tuple!(int, float)?

Yes, even when that literal sucks =)
 I'm not convinced - at all, in fact. Right now Tuple is on equal footing
 with other templates and whatever introspection we have/will add
 works/will work on Tuple as it works with other templates. With the
 extra syntax, we'll then need to add special methods for introspecting
 a tuple. We'll find ourselves also reserving a keyword "tuple" and
 positing that [: ... :] is the same as tuple!(...) or some other
 similarly unpleasant solution. Plus, special syntax contributes to the
 disconnect between user-defined and built-in. This creates the
 self-perpetuating trend that if anything is interesting, it should have
 a literal allocated to it. Instead of that, let's think e.g. of methods
 to generally make parameterized types look better.

This is all very nice theory, but in the practice, my 2 previos points stands. I'm sorry to keep quoting Python stuff, I agree pretty much with The Zen if Python (python -m this): Special cases aren't special enough to break the rules. Although practicality beats purity. =) -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- They love me like I was a brother They protect me, listen to me They dug me my very own garden Gave me sunshine, made me happy Nice dream, nice dream Nice dream
Apr 01 2009
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Wed, Apr 1, 2009 at 5:03 AM, Sergey Gromov <snake.scaly gmail.com> wrote:
 Tue, 31 Mar 2009 12:18:21 -0700, Andrei Alexandrescu wrote:

 Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 1:32 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) = someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) = someFunction();



{ alias T Tuple; } Tuple!(int, float) foo() { return Tuple!(3, 4.5); } foo.d(10): Error: functions cannot return a tuple Unless you're using some prerelease compiler, they are not.

Tuple!(int, float) foo() { return tuple(2, 4.5); } The addition of the alias this feature and of constructor templates makes std.typecons.Tuple even better. Andrei

Well, basically struct is a run-time tuple, anyway. I think that all the buzz around "actual tuple support" boils down to requests for syntax sugar for construction and decomposition of anonymous structs. While typecons.Tuple is sorta OK for construction, things are still pretty ugly on the "decomposition" end.

For me the distinction is that I would only consider writing a function that returns something like "Tuple!(int, float)" as a last resort when no other design would work. I would sooner use two out parameters.

Why? I use tuple returns all over.
 But in Python or ML, no question. I'd happily write a function that
 returns (2, 4.2) without giving it much thought.  Now perhaps cogent
 arguments like "blech" and "belch" can convince me that I should
 embrace the Tuple!(int,float) and use it everywhere, just like I'd use
 tuples in Python and ML, but so far I'm not convinced.
 
 To me it seems to be in the same league as int[] vs std::vector<int>.
 int[] -- great I'll happily use that everywhere.  std::vector<int>
 kind of a pain, use begrudgingly as needed.

Well I think a language can only have so many built-in types. We can't go on forever. Andrei
Mar 31 2009
next sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
Andrei Alexandrescu, el 31 de marzo a las 17:55 me escribiste:
But in Python or ML, no question. I'd happily write a function that
returns (2, 4.2) without giving it much thought.  Now perhaps cogent
arguments like "blech" and "belch" can convince me that I should
embrace the Tuple!(int,float) and use it everywhere, just like I'd use
tuples in Python and ML, but so far I'm not convinced.
To me it seems to be in the same league as int[] vs std::vector<int>.
int[] -- great I'll happily use that everywhere.  std::vector<int>
kind of a pain, use begrudgingly as needed.

Well I think a language can only have so many built-in types. We can't go on forever.

You don't have to. There are very few types that are extremely useful to build up things having a good syntax. I think Python got this right: tuples, lists, hashes. That's all you need as first class citizens (speaking of "containers"). I think D is only missing tuples (dynamic arrays works just fine as lists in D). -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- The Muppet show was banned from TV in Saudi Arabia Because one of its stars was a pig
Mar 31 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Leandro Lucarella wrote:
 Andrei Alexandrescu, el 31 de marzo a las 17:55 me escribiste:
 But in Python or ML, no question. I'd happily write a function that
 returns (2, 4.2) without giving it much thought.  Now perhaps cogent
 arguments like "blech" and "belch" can convince me that I should
 embrace the Tuple!(int,float) and use it everywhere, just like I'd use
 tuples in Python and ML, but so far I'm not convinced.
 To me it seems to be in the same league as int[] vs std::vector<int>.
 int[] -- great I'll happily use that everywhere.  std::vector<int>
 kind of a pain, use begrudgingly as needed.

go on forever.

You don't have to. There are very few types that are extremely useful to build up things having a good syntax. I think Python got this right: tuples, lists, hashes. That's all you need as first class citizens (speaking of "containers"). I think D is only missing tuples (dynamic arrays works just fine as lists in D).

So we must add lists too. Andrei
Mar 31 2009
next sibling parent Leandro Lucarella <llucax gmail.com> writes:
Andrei Alexandrescu, el 31 de marzo a las 18:42 me escribiste:
 Leandro Lucarella wrote:
Andrei Alexandrescu, el 31 de marzo a las 17:55 me escribiste:
But in Python or ML, no question. I'd happily write a function that
returns (2, 4.2) without giving it much thought.  Now perhaps cogent
arguments like "blech" and "belch" can convince me that I should
embrace the Tuple!(int,float) and use it everywhere, just like I'd use
tuples in Python and ML, but so far I'm not convinced.
To me it seems to be in the same league as int[] vs std::vector<int>.
int[] -- great I'll happily use that everywhere.  std::vector<int>
kind of a pain, use begrudgingly as needed.

go on forever.

build up things having a good syntax. I think Python got this right: tuples, lists, hashes. That's all you need as first class citizens (speaking of "containers"). I think D is only missing tuples (dynamic


arrays works just fine as lists in D).


 So we must add lists too.

Are you ignoring what I'm writing on purpose? =) -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- He used to do surgery On girls in the eighties But gravity always wins
Mar 31 2009
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

 So we must add lists too.

Notice the the python "list" is an array dynamic on the right, it's not a linked list. Regarding tuple: I don't like the name "tuple" of typecons, because they aren't the tuples of D, they are structs. That's why I have named them Record/record in my dlibs. In my dlibs Tuple is: template Tuple(T...) { alias T Tuple; } Also, tuple of typecons misses some very important methods. ---------------------- Andrei Alexandrescu:
Would the special set syntax look a ton better than

set("ab", "c") ?< I agree, that's acceptable. That's how they are implemented in my d.sets.
I guess I can't bring myself to dislike tuple(1, 2) in D.<

"I don't agree": a built-in tuple allows you some of the other things I have shown you in Python. --------------- Bill Baxter:
Walter read a paper by a numerical math guy stating that some things just can't
be done correctly if complex types aren't part of the language.<

Maybe you are talking about William Kahan, a person that knows more than the square of what you, me and Walter knows :-) See Complex Arithmetic Class here: http://www.eecs.berkeley.edu/~wkahan/JAVAhurt.pdf
And I guess it seemed true at the time.   But since then they have figured out
a way to make the compiler clever enough to handle such cases correctly even
without it being built-in.<

Do you have references or links that can show me that what Kahan says there is not longer necessary/true? Bye, bearophile
Mar 31 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
bearophile wrote:
 Andrei Alexandrescu:
 
 So we must add lists too.

Notice the the python "list" is an array dynamic on the right, it's not a linked list.

I know. My point was that I might want to add a reasonable data structure to the language, and it's hard to build an argument on what to leave out and what to put in.
 Regarding tuple: I don't like the name "tuple" of typecons, because
 they aren't the tuples of D, they are structs. That's why I have
 named them Record/record in my dlibs.

D is at fault because it called typelists tuples. I told Walter not to, and he went ahead and did so anyway. Now we're living with the consequences.
 In my dlibs Tuple is: template Tuple(T...) { alias T Tuple; }

That's a typelist.
 Also, tuple of typecons misses some very important methods.

I added a few (soon to be released). Andrei
Mar 31 2009
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

D is at fault because it called typelists tuples. I told Walter not to, and he
went ahead and did so anyway. Now we're living with the consequences.<

I see, and you are right. Then why not rename tuples of D2 to a more correct name (typelists)? Being D2 in alpha still there's time to rename invariant as immutable, tuples as typelists... :-) Giving the right names to things is important.
I added a few (soon to be released).<

May I ask what ones? My Records (of D1) have: - attribute length - opCmp that uses a recursive structCmp() that works even with nested normal structs tpp :-) - opEquals - toHash (this too is recursive nested normal structs too) - opIn_r - toString - opCat, that attaches a Record to another Record/generic struct, creating a new Record. All that is useful. This allows them to work almost as Python tuples. But Record/record doesn't support a good unpacking syntax, of course. You may need compiler support for this. Bye, bearophile
Mar 31 2009
prev sibling parent Max Samukha <samukha voliacable.com.removethis> writes:
On Tue, 31 Mar 2009 23:07:46 -0700, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:

bearophile wrote:
 Andrei Alexandrescu:
 
 So we must add lists too.

Notice the the python "list" is an array dynamic on the right, it's not a linked list.

I know. My point was that I might want to add a reasonable data structure to the language, and it's hard to build an argument on what to leave out and what to put in.
 Regarding tuple: I don't like the name "tuple" of typecons, because
 they aren't the tuples of D, they are structs. That's why I have
 named them Record/record in my dlibs.

D is at fault because it called typelists tuples. I told Walter not to, and he went ahead and did so anyway. Now we're living with the consequences.
 In my dlibs Tuple is: template Tuple(T...) { alias T Tuple; }

That's a typelist.

language, not only types?
 Also, tuple of typecons misses some very important methods.

I added a few (soon to be released). Andrei

Apr 01 2009
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

 Well I think a language can only have so many built-in types. We can't 
 go on forever.

Too many built-ins become confusing (see Fortress), but D is quite far from that point (see Python, that has more than D and they are just fine and easy to use and remember. I'd also like to add a set literal to the D syntax, semantically implemented in the std library). On the other hand Scala language shows that a good language allows you to remove things from the language/syntax and implement them as libraries (Scala moves in the libs several things that are built-in in D). So it's a dynamic balance, things go, things come. But note that collection "literals" of Scala are worse than Python ones. --------------- Sergey Gromov:
Comma expression is not ambiguous.  It's a comma expression.  Renaming it into
a tuple constructor expression does not add any ambiguity. Parentheses here are
only required to separate the comma expression from an assignment expression
which otherwise would become a part of comma expression.<

Python has tuples, but their syntax has some holes I have never fully loved. See: Empty tuple: () Tuple with 1 item: 1, Or (1,) Tuple with two items: 1, 2 Or: (1, 2) They also support smarter forms of unpacking (Python 2.6): def foo((x, y)): Now if you pass foo a pair (a 2-list, 2-tuple, 2-string, 2-lazy iterable, 2-array, 2-set, 2-dict, etc) you have available and assigned x and y inside foo. In the following syntax (Python 3.0+), c becomes assigned with all the items following the second one: a, b, *c = baz In the end I don't like the use of () to denote tuples (well, in Python most of the times it's the comma that denotes a tuple, only empty tuples needs () ). So better to use different ways to denote them. Bye, bearophile
Mar 31 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
bearophile wrote:
 Andrei Alexandrescu:
 
 Well I think a language can only have so many built-in types. We
 can't go on forever.

Too many built-ins become confusing (see Fortress), but D is quite far from that point (see Python, that has more than D and they are just fine and easy to use and remember. I'd also like to add a set literal to the D syntax, semantically implemented in the std library).

Would the special set syntax look a ton better than set(1, 2, 5, 6) set("ab", "c") ?
 On the other hand Scala language shows that a good language allows
 you to remove things from the language/syntax and implement them as
 libraries (Scala moves in the libs several things that are built-in
 in D). So it's a dynamic balance, things go, things come. But note
 that collection "literals" of Scala are worse than Python ones.
 
 ---------------
 
 Sergey Gromov:
 
 Comma expression is not ambiguous.  It's a comma expression.
 Renaming it into a tuple constructor expression does not add any
 ambiguity. Parentheses here are only required to separate the comma
 expression from an assignment expression which otherwise would
 become a part of comma expression.<

Python has tuples, but their syntax has some holes I have never fully loved. See: Empty tuple: () Tuple with 1 item: 1, Or (1,) Tuple with two items: 1, 2 Or: (1, 2) They also support smarter forms of unpacking (Python 2.6): def foo((x, y)): Now if you pass foo a pair (a 2-list, 2-tuple, 2-string, 2-lazy iterable, 2-array, 2-set, 2-dict, etc) you have available and assigned x and y inside foo. In the following syntax (Python 3.0+), c becomes assigned with all the items following the second one: a, b, *c = baz In the end I don't like the use of () to denote tuples (well, in Python most of the times it's the comma that denotes a tuple, only empty tuples needs () ). So better to use different ways to denote them. Bye, bearophile

I guess I can't bring myself to dislike tuple(1, 2) in D. Andrei
Mar 31 2009
next sibling parent dsimcha <dsimcha yahoo.com> writes:
== Quote from Bill Baxter (wbaxter gmail.com)'s article
 On Wed, Apr 1, 2009 at 10:53 AM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 I guess I can't bring myself to dislike tuple(1, 2) in D.

Especially if using it didn't require any explicit import. --bb

Yeah, IMHO, some of the really basic library functions that would be builtins in other languages should be implicitly imported in Object. Yes, namespace pollution is generally a bad thing, but noone in their right mind would name some arbitrary function max(), map(), filter(), etc. anyhow because that's just really bad naming. Given that functions with these names have such standard, well-defined meanings, trying to use these names for arbitrary functions is only marginally smarter than trying to name your function after some keyword. The fact that D can support these features well as libraries and they don't need to be built in is a good thing, and they should remain as libraries. It's just that for such basic, commonly used functions, even the mental burden of having to remember to import them is too much, and this problem is trivial to fix.
Mar 31 2009
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Wed, Apr 1, 2009 at 10:53 AM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 
 I guess I can't bring myself to dislike tuple(1, 2) in D.

I'd actually be a heck of a lot happier with that than Tuple!(1,2). Especially if using it didn't require any explicit import. --bb

Tuple!(...) tuple(...) { ... } is already in std.typecons. Andrei
Mar 31 2009
prev sibling next sibling parent dsimcha <dsimcha yahoo.com> writes:
== Quote from Bill Baxter (wbaxter gmail.com)'s article
 Ok, then we'll introduce balanced budget amendment for types to ensure
 this doesn't happen.  For every new type added one must be removed.
 We're going to vote complex types off the island, right?   Maybe we
 could get rid of associative arrays as a built-in too.
 --bb

Aren't builtin complex types on the way out anyhow? (See http://digitalmars.com/d/2.0/phobos/std_complex.html). I always found them to be quite peculiar, as they really only are useful for a niche within a niche. Specifically, noone outside scientific computing (already a small subset of programmers) would use them, and even then, only a subset of scientific computing people need them. I personally do scientific computing (specifically bioinformatics, which for those of you who aren't familiar with the field is mostly stochastic models and data mining as applied to molecular biology), and I have never in my life used D's complex numbers. My guess is that Walter, having a mech e. degree, drastically overestimated early in D's design how many people actually use complex numbers. I know enough mechanical and electrical engineers and physicists to know that they simply love complex numbers.
Mar 31 2009
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 Ok, then we'll introduce balanced budget amendment for types to ensure
 this doesn't happen.  For every new type added one must be removed.
 We're going to vote complex types off the island, right?   Maybe we
 could get rid of associative arrays as a built-in too.

Ironic as that might be, I wouldn't mind it. The syntax of associative array types is nice, but other than that they are terribly opaque to introspection. If I could, I'd say T[U] rewrites into Hash!(U, T) and then Hash is defined in object.d. Andrei
Mar 31 2009
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 3:18 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 import std.typecons;

 Tuple!(int, float) foo()
 {
    return tuple(2, 4.5);
 }

 The addition of the alias this feature and of constructor templates makes
 std.typecons.Tuple even better.

Cool, but.. Why not just make tuples first-class types? <_<

Why not not? Andrei
Mar 31 2009
next sibling parent grauzone <none example.net> writes:
Andrei Alexandrescu wrote:
 Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 3:18 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 import std.typecons;

 Tuple!(int, float) foo()
 {
    return tuple(2, 4.5);
 }

 The addition of the alias this feature and of constructor templates 
 makes
 std.typecons.Tuple even better.

Cool, but.. Why not just make tuples first-class types? <_<

Why not not?

Why not remove return values in favour of out parameters? That makes overloading on return values instantly possible, and removes complexity from the language and the compiler. The disadvantage of not being able to use functions in expressions could be removed by library support. We can use string mixins and CTFE to do this: void add(T)(T a, T b, out T result); mixin(expr("assert(add(1, 2, #ret) == 3)); This is an advantage over the old design, because the complex issue about handling return values is moved from the compiler into the library, and thus is more flexible and more customizable. Users could even write their own expr() template to support multiple return values.
 Andrei

Mar 31 2009
prev sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Andrei Alexandrescu wrote:
 Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 3:18 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 import std.typecons;

 Tuple!(int, float) foo()
 {
    return tuple(2, 4.5);
 }

 The addition of the alias this feature and of constructor templates
 makes
 std.typecons.Tuple even better.

Cool, but.. Why not just make tuples first-class types? <_<

Why not not? Andrei

Because people keep having to invent hacks to work around the fact that we can't return tuples. std.typecons.Tuple is a perfect example of this. -- Daniel
Mar 31 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Daniel Keep wrote:
 
 Andrei Alexandrescu wrote:
 Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 3:18 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 import std.typecons;

 Tuple!(int, float) foo()
 {
    return tuple(2, 4.5);
 }

 The addition of the alias this feature and of constructor templates
 makes
 std.typecons.Tuple even better.

Why not just make tuples first-class types? <_<

Andrei

Because people keep having to invent hacks to work around the fact that we can't return tuples. std.typecons.Tuple is a perfect example of this.

"It's not a hack, it's a feature." If you don't have a list in the language and build it as a user-defined type, is that a hack? Andrei
Mar 31 2009
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Andrei Alexandrescu wrote:
 Daniel Keep wrote:
 Andrei Alexandrescu wrote:
 Jarrett Billingsley wrote:
 ...

 Why not just make tuples first-class types?  <_<

Andrei

Because people keep having to invent hacks to work around the fact that we can't return tuples. std.typecons.Tuple is a perfect example of this.

"It's not a hack, it's a feature." If you don't have a list in the language and build it as a user-defined type, is that a hack? Andrei

Only if the language itself has lists except you can't return them from functions, and you have to wrap them in a struct to make that work. Except then you can't index them, so you have to add "alias this;" to make *that* work. :P -- Daniel
Mar 31 2009
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
dsimcha <dsimcha yahoo.com> wrote:

 == Quote from Denis Koroskin (2korden gmail.com)'s article
 That said, I don't think there is a need for something like this.
 Certainly no speedup and little clarity compared to declaring variable
 right before invoking doStuff.

Here's an example of where it would be a useful piece of sugar, given an unpack function that I was playing with: // How it works now: uint foo; string bar; unpack(foo, bar) = someFunction(); // vs. how I want it to work: unpack(auto foo, auto bar) = someFunction();

If foo and bar die right after this line, I feel this is acceptable. But declaring variables inside a function call seems to me hard to decipher and hardly ever a good idea. -- Simen
Mar 31 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) = someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) = someFunction();

Cute, but uh, I'd much rather see tuples just be returnable. That would practically remove the need for out parameters, and would remove the need for this request as well (since that's about the only time you'd need it).
Mar 31 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Tue, Mar 31, 2009 at 1:32 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) = someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) = someFunction();

Cute, but uh, I'd much rather see tuples just be returnable.

They are.

template Tuple(T...) { alias T Tuple; } Tuple!(int, float) foo() { return Tuple!(3, 4.5); } foo.d(10): Error: functions cannot return a tuple Unless you're using some prerelease compiler, they are not.
Mar 31 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Tue, Mar 31, 2009 at 3:18 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 import std.typecons;

 Tuple!(int, float) foo()
 {
 =A0 =A0return tuple(2, 4.5);
 }

 The addition of the alias this feature and of constructor templates makes
 std.typecons.Tuple even better.

Cool, but.. Why not just make tuples first-class types? <_<
Mar 31 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Wed, Apr 1, 2009 at 5:03 AM, Sergey Gromov <snake.scaly gmail.com> wrote=
:
 Tue, 31 Mar 2009 12:18:21 -0700, Andrei Alexandrescu wrote:

 Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 1:32 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) =3D someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) =3D someFunction();



template Tuple(T...) { =A0 =A0 =A0alias T Tuple; } Tuple!(int, float) foo() { =A0 =A0 =A0return Tuple!(3, 4.5); } foo.d(10): Error: functions cannot return a tuple Unless you're using some prerelease compiler, they are not.

import std.typecons; Tuple!(int, float) foo() { =A0 =A0 =A0return tuple(2, 4.5); } The addition of the alias this feature and of constructor templates makes std.typecons.Tuple even better. Andrei

Unfair---std.typecons.Tuple is actually a struct! Well, basically struct is a run-time tuple, anyway. I think that all the buzz around "actual tuple support" boils down to requests for syntax sugar for construction and decomposition of anonymous structs. =A0While typecons.Tuple is sorta OK for construction, things are still pretty ugly on the "decomposition" end.

Right. In my ideal world I could use tuples like this: (int,float) a; a =3D returns_tuple(); a[0] =3D 2; a[1] =3D 3.4; (int,float) z =3D returns_tuple(); (int x, float y) =3D returns_tuple(); auto tup =3D (2, 3.4); takes_int_and_float(unpack!(tup)); I think experience with tuples in Python and ML (and probably elsewhere -- heck even D) shows that tuples are incredibly useful. So useful that they deserve better syntax than Tuple!(...). --bb
Mar 31 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Wed, Apr 1, 2009 at 6:16 AM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Wed, Apr 1, 2009 at 5:03 AM, Sergey Gromov <snake.scaly gmail.com>
 wrote:
 Tue, 31 Mar 2009 12:18:21 -0700, Andrei Alexandrescu wrote:

 Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 1:32 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) =3D someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) =3D someFunction();

Cute, but uh, I'd much rather see tuples just be returnable.

They are.

template Tuple(T...) { =A0 =A0 alias T Tuple; } Tuple!(int, float) foo() { =A0 =A0 return Tuple!(3, 4.5); } foo.d(10): Error: functions cannot return a tuple Unless you're using some prerelease compiler, they are not.

import std.typecons; Tuple!(int, float) foo() { =A0 =A0 return tuple(2, 4.5); } The addition of the alias this feature and of constructor templates makes std.typecons.Tuple even better. Andrei

Unfair---std.typecons.Tuple is actually a struct! Well, basically struct is a run-time tuple, anyway. I think that all the buzz around "actual tuple support" boils down to requests for syntax sugar for construction and decomposition of anonymous structs. =A0While typecons.Tuple is sorta OK for construction=



 things are still pretty ugly on the "decomposition" end.

Right. =A0In my ideal world I could use tuples like this: (int,float) a;

That sucks. Is int(int, float) a function type or a juxtaposition of two types? Is (A, B) an expression or a type? And so on.
 a =3D returns_tuple();

 a[0] =3D 2;
 a[1] =3D 3.4;

That works in my tree already due to alias this.
 (int,float) z =3D returns_tuple();

Blech.
 (int x, float y) =3D returns_tuple();

I'd like that too, but what we should have is make any definition an expression.
 auto tup =3D (2, 3.4);

Belch (sic).
 takes_int_and_float(unpack!(tup));

Meh.
 I think experience with tuples in Python and ML (and probably
 elsewhere -- heck even D) shows that tuples are incredibly useful. =A0So
 useful that they deserve better syntax than Tuple!(...).

Ehm.

Thanks for that insightful analysis and commentary. :) --bb
Mar 31 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Wed, Apr 1, 2009 at 6:16 AM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Wed, Apr 1, 2009 at 5:03 AM, Sergey Gromov <snake.scaly gmail.com>
 wrote:
 Tue, 31 Mar 2009 12:18:21 -0700, Andrei Alexandrescu wrote:

 Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 1:32 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) =3D someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) =3D someFunction();

Cute, but uh, I'd much rather see tuples just be returnable.

They are.

template Tuple(T...) { =A0 =A0 alias T Tuple; } Tuple!(int, float) foo() { =A0 =A0 return Tuple!(3, 4.5); } foo.d(10): Error: functions cannot return a tuple Unless you're using some prerelease compiler, they are not.

import std.typecons; Tuple!(int, float) foo() { =A0 =A0 return tuple(2, 4.5); } The addition of the alias this feature and of constructor templates makes std.typecons.Tuple even better. Andrei

Unfair---std.typecons.Tuple is actually a struct! Well, basically struct is a run-time tuple, anyway. I think that all the buzz around "actual tuple support" boils down to requests for syntax sugar for construction and decomposition of anonymous structs. =A0While typecons.Tuple is sorta OK for construction=



 things are still pretty ugly on the "decomposition" end.

Right. =A0In my ideal world I could use tuples like this: (int,float) a;

That sucks. Is int(int, float) a function type or a juxtaposition of two types?

I should say that by "in my ideal world" what I meant was "forgetting about all the baggage that D already has for a moment and starting from a more or less clean slate". Things like the useless comma operator. But isn't a juxtaposition of two types a syntax error? So the above would be a function type, not a juxtaposition of two types.
 Is (A, B) an expression or a type? And so on.

How does that differ from asking "Is A an expression or a type?" If A and B are types, then (A,B) is a type.
 (int,float) z =3D returns_tuple();

Blech.

Blech to that, but you like Tuple!(int,float) z =3D returns_tuple(); correct?
 (int x, float y) =3D returns_tuple();

I'd like that too, but what we should have is make any definition an expression.
 auto tup =3D (2, 3.4);

Belch (sic).

Belch to that, but again, you're saying this is great auto tup =3D Tuple!(2, 3.4); correct? --bb
Mar 31 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Wed, Apr 1, 2009 at 5:03 AM, Sergey Gromov <snake.scaly gmail.com> wrote=
:
 Tue, 31 Mar 2009 12:18:21 -0700, Andrei Alexandrescu wrote:

 Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 1:32 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) =3D someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) =3D someFunction();



template Tuple(T...) { =A0 =A0 =A0alias T Tuple; } Tuple!(int, float) foo() { =A0 =A0 =A0return Tuple!(3, 4.5); } foo.d(10): Error: functions cannot return a tuple Unless you're using some prerelease compiler, they are not.

import std.typecons; Tuple!(int, float) foo() { =A0 =A0 =A0return tuple(2, 4.5); } The addition of the alias this feature and of constructor templates makes std.typecons.Tuple even better. Andrei

Unfair---std.typecons.Tuple is actually a struct! Well, basically struct is a run-time tuple, anyway. I think that all the buzz around "actual tuple support" boils down to requests for syntax sugar for construction and decomposition of anonymous structs. =A0While typecons.Tuple is sorta OK for construction, things are still pretty ugly on the "decomposition" end.

For me the distinction is that I would only consider writing a function that returns something like "Tuple!(int, float)" as a last resort when no other design would work. I would sooner use two out parameters. But in Python or ML, no question. I'd happily write a function that returns (2, 4.2) without giving it much thought. Now perhaps cogent arguments like "blech" and "belch" can convince me that I should embrace the Tuple!(int,float) and use it everywhere, just like I'd use tuples in Python and ML, but so far I'm not convinced. To me it seems to be in the same league as int[] vs std::vector<int>. int[] -- great I'll happily use that everywhere. std::vector<int> kind of a pain, use begrudgingly as needed. --bb
Mar 31 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Wed, Apr 1, 2009 at 9:55 AM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Wed, Apr 1, 2009 at 5:03 AM, Sergey Gromov <snake.scaly gmail.com>
 wrote:
 Tue, 31 Mar 2009 12:18:21 -0700, Andrei Alexandrescu wrote:

 Jarrett Billingsley wrote:
 On Tue, Mar 31, 2009 at 1:32 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 2009/3/30 dsimcha <dsimcha yahoo.com>:
 // How it works now:
 uint foo;
 string bar;
 unpack(foo, bar) =3D someFunction();

 // vs. how I want it to work:
 unpack(auto foo, auto bar) =3D someFunction();

Cute, but uh, I'd much rather see tuples just be returnable.

They are.

template Tuple(T...) { =A0 =A0 alias T Tuple; } Tuple!(int, float) foo() { =A0 =A0 return Tuple!(3, 4.5); } foo.d(10): Error: functions cannot return a tuple Unless you're using some prerelease compiler, they are not.

import std.typecons; Tuple!(int, float) foo() { =A0 =A0 return tuple(2, 4.5); } The addition of the alias this feature and of constructor templates makes std.typecons.Tuple even better. Andrei

Unfair---std.typecons.Tuple is actually a struct! Well, basically struct is a run-time tuple, anyway. I think that all the buzz around "actual tuple support" boils down to requests for syntax sugar for construction and decomposition of anonymous structs. =A0While typecons.Tuple is sorta OK for construction=



 things are still pretty ugly on the "decomposition" end.

For me the distinction is that I would only consider writing a function that returns something like "Tuple!(int, float)" as a last resort when no other design would work. =A0I would sooner use two out parameters.

Why? I use tuple returns all over.

It could just be paranoia, but I prefer to avoid dependency on a library type if it is possible. If I use a library type as a part of my code's public interface I'm saying that the functionality provided by that library is so important that I think all users of my library should use it also. But this is the one negative reaction to Tuple!() that I could probably be convinced to overcome. For instance if it becomes clear that everyone will be able to use Phobos and love and adore it, then I think that issue goes away for me. (But not the ugly syntax issue). But I'm not quite there yet believing that, because y'know Phobos hasn't historically been so good at getting everyone to adore it.
 But in Python or ML, no question. I'd happily write a function that
 returns (2, 4.2) without giving it much thought. =A0Now perhaps cogent
 arguments like "blech" and "belch" can convince me that I should
 embrace the Tuple!(int,float) and use it everywhere, just like I'd use
 tuples in Python and ML, but so far I'm not convinced.

 To me it seems to be in the same league as int[] vs std::vector<int>.
 int[] -- great I'll happily use that everywhere. =A0std::vector<int>
 kind of a pain, use begrudgingly as needed.

Well I think a language can only have so many built-in types. We can't go=

 forever.

Ok, then we'll introduce balanced budget amendment for types to ensure this doesn't happen. For every new type added one must be removed. We're going to vote complex types off the island, right? Maybe we could get rid of associative arrays as a built-in too. --bb
Mar 31 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Wed, Apr 1, 2009 at 10:53 AM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:

 I guess I can't bring myself to dislike tuple(1, 2) in D.

I'd actually be a heck of a lot happier with that than Tuple!(1,2). Especially if using it didn't require any explicit import. --bb
Mar 31 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Wed, Apr 1, 2009 at 11:15 AM, dsimcha <dsimcha yahoo.com> wrote:
 =3D=3D Quote from Bill Baxter (wbaxter gmail.com)'s article
 We're going to vote complex types off the island, right? =A0 Maybe we
 could get rid of associative arrays as a built-in too.

Aren't builtin complex types on the way out anyhow?

Right. That's what I meant. But I feared my tuple for complex exchange would not be accepted because the demise of complex was already announced. So I threw in associative arrays too.
=A0(See
 http://digitalmars.com/d/2.0/phobos/std_complex.html). =A0I always found =

 quite peculiar, as they really only are useful for a niche within a niche=

 Specifically, noone outside scientific computing (already a small subset =

 programmers) would use them, and even then, only a subset of scientific c=

 people need them. =A0I personally do scientific computing (specifically
 bioinformatics, which for those of you who aren't familiar with the field=

 mostly stochastic models and data mining as applied to molecular biology)=

 have never in my life used D's complex numbers.

 My guess is that Walter, having a mech e. degree, drastically overestimat=

 in D's design how many people actually use complex numbers. =A0I know eno=

 mechanical and electrical engineers and physicists to know that they simp=

 complex numbers.

Walter read a paper by a numerical math guy stating that some things just can't be done correctly if complex types aren't part of the language. And I guess it seemed true at the time. But since then they have figured out a way to make the compiler clever enough to handle such cases correctly even without it being built-in. --bb
Mar 31 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Wed, Apr 1, 2009 at 1:12 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Wed, Apr 1, 2009 at 10:53 AM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 I guess I can't bring myself to dislike tuple(1, 2) in D.

I'd actually be a heck of a lot happier with that than Tuple!(1,2). Especially if using it didn't require any explicit import. --bb

Tuple!(...) tuple(...) { ... } is already in std.typecons.

Ok,didn't realize that. But with that tuple(int,float) doesn't compile, right? I thought you were proposing that you could get rid of Tuple!() entirely somehow and replace it with tuple(). That is what I meant I could go for. --bb
Mar 31 2009