www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Yet another MRV proposal!

reply downs <default_357-line yahoo.de> writes:
Let's give this another try.
The following proposal has the advantage that it's funded mostly on existing
syntax.

An anonymous struct, in the position where you'd normally expect a
function/method return type, is usable as the return type instead.

Example:

struct { int a; float b; } test() { return(1, 2f); }

writefln(test().a, test().b);

The compiler would translate this into "current D" as follows:

struct _D_anonymous_struct_1 { int a; float b; }
_D_anonymous_struct_1 test() { return _D_anonymous_struct_1(1, 2f); }

Because of the not-exactly-clear type name, it is necessary to store the
returned value in an auto/const/static variable.

This looks like it could be ambiguous, but it really isn't - the two conditions
required here - an unnamed struct in the position where a return type would be
expected - are quite unambiguous :)

Whaddya think?

 --downs
Apr 14 2008
next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
downs wrote:
 Let's give this another try.
 The following proposal has the advantage that it's funded mostly on existing
syntax.
 
 An anonymous struct, in the position where you'd normally expect a
function/method return type, is usable as the return type instead.
 
 Example:
 
 struct { int a; float b; } test() { return(1, 2f); }
 
 writefln(test().a, test().b);
 
 The compiler would translate this into "current D" as follows:
 
 struct _D_anonymous_struct_1 { int a; float b; }
 _D_anonymous_struct_1 test() { return _D_anonymous_struct_1(1, 2f); }
 
 Because of the not-exactly-clear type name, it is necessary to store the
returned value in an auto/const/static variable.
 
 This looks like it could be ambiguous, but it really isn't - the two
conditions required here - an unnamed struct in the position where a return
type would be expected - are quite unambiguous :)
 
 Whaddya think?
 
  --downs
It does seem reasonable that you should be able to return an anonymous struct (or class). I guess for a no-element struct you could use "return (); "? Or for an anon struct with default values. struct{int a=1; int b=2;} foo() { return(); } The return becomes like an invocation of static opCall, except you leave the name of the struct off, because it's anonymous. For classes syntax could be like class{int a=1; int b=2;} foo() { return new (); } Do you have a need for this? --bb
Apr 14 2008
next sibling parent downs <default_357-line yahoo.de> writes:
Bill Baxter wrote:
 downs wrote:
 Let's give this another try.
 The following proposal has the advantage that it's funded mostly on
 existing syntax.

 An anonymous struct, in the position where you'd normally expect a
 function/method return type, is usable as the return type instead.

 Example:

 struct { int a; float b; } test() { return(1, 2f); }

 writefln(test().a, test().b);

 The compiler would translate this into "current D" as follows:

 struct _D_anonymous_struct_1 { int a; float b; }
 _D_anonymous_struct_1 test() { return _D_anonymous_struct_1(1, 2f); }

 Because of the not-exactly-clear type name, it is necessary to store
 the returned value in an auto/const/static variable.

 This looks like it could be ambiguous, but it really isn't - the two
 conditions required here - an unnamed struct in the position where a
 return type would be expected - are quite unambiguous :)

 Whaddya think?

  --downs
It does seem reasonable that you should be able to return an anonymous struct (or class). I guess for a no-element struct you could use "return (); "? Or for an anon struct with default values. struct{int a=1; int b=2;} foo() { return(); } The return becomes like an invocation of static opCall, except you leave the name of the struct off, because it's anonymous. For classes syntax could be like class{int a=1; int b=2;} foo() { return new (); } Do you have a need for this? --bb
Makes sense to extend it to all types that can be anonymously declared. Except unions. That'd be asking too much. :p That being said, this is not, per se, a "needed" feature - you can always just give the struct a name and say struct Foo { int a; float b; } Foo test() { return Foo(2, 3f); } The problem with this is that you need to repeat the name of the struct thrice in all, more if you have more return statements, whereas the name is often quite irrelevant and redundant :) The other advantage is that it seems like it would be relatively easy to implement, seeing as all that's needed is allowing to declare anonymous structs outside of their current contexts, and having them evaluate to their own type. (and the return syntax) --downs
Apr 14 2008
prev sibling parent "Hans W. Uhlig" <huhlig gmail.com> writes:
Bill Baxter wrote:
 downs wrote:
 Let's give this another try.
 The following proposal has the advantage that it's funded mostly on 
 existing syntax.

 An anonymous struct, in the position where you'd normally expect a 
 function/method return type, is usable as the return type instead.

 Example:

 struct { int a; float b; } test() { return(1, 2f); }

 writefln(test().a, test().b);

 The compiler would translate this into "current D" as follows:

 struct _D_anonymous_struct_1 { int a; float b; }
 _D_anonymous_struct_1 test() { return _D_anonymous_struct_1(1, 2f); }

 Because of the not-exactly-clear type name, it is necessary to store 
 the returned value in an auto/const/static variable.

 This looks like it could be ambiguous, but it really isn't - the two 
 conditions required here - an unnamed struct in the position where a 
 return type would be expected - are quite unambiguous :)

 Whaddya think?

  --downs
It does seem reasonable that you should be able to return an anonymous struct (or class). I guess for a no-element struct you could use "return (); "? Or for an anon struct with default values. struct{int a=1; int b=2;} foo() { return(); } The return becomes like an invocation of static opCall, except you leave the name of the struct off, because it's anonymous. For classes syntax could be like class{int a=1; int b=2;} foo() { return new (); } Do you have a need for this? --bb
I agree with this an it was part of what I was hashing out with the alternate declaration syntax. Having Multiple return values in a const environment seems to me to lead to an easier transition to parallel processing in an imperative environment. Technically yes, you can manually generate a struct for each function needing to return multiple values back. Multiple const/invariant in and one out seems to me at least to be a flaw in design. Since once the input date is frozen and passed in, it becomes immutable and then gets duped inside the function and dealt with. A simple method for returning multiple non const values back out(to be reintegrated with the larger DS, filed or whatnot) would be very useful. However as Scott has shown me I do not necessarily understand the implementations of these ideas, only the academic principles.
Apr 18 2008
prev sibling next sibling parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Mon, 14 Apr 2008 11:23:50 +0200, downs <default_357-line yahoo.de>  =

wrote:

 Let's give this another try.
 The following proposal has the advantage that it's funded mostly on  =
 existing syntax.

 An anonymous struct, in the position where you'd normally expect a  =
 function/method return type, is usable as the return type instead.

 Example:

 struct { int a; float b; } test() { return(1, 2f); }

 writefln(test().a, test().b);

 The compiler would translate this into "current D" as follows:

 struct _D_anonymous_struct_1 { int a; float b; }
 _D_anonymous_struct_1 test() { return _D_anonymous_struct_1(1, 2f); }

 Because of the not-exactly-clear type name, it is necessary to store t=
he =
 returned value in an auto/const/static variable.

 This looks like it could be ambiguous, but it really isn't - the two  =
 conditions required here - an unnamed struct in the position where a  =
 return type would be expected - are quite unambiguous :)

 Whaddya think?

  --downs
Looks pretty good - there are reasons to allow returning anonymous structs, and I'm sure they could find uses in other places as well. One problem I see is that, compared to 'true' MRV, it requires extra assignments if you want the values outside the struct. int a; float b; struct { int a; float b; } test() { return(1, 2f); } auto result =3D test(); a =3D result.a; // These should b =3D result.b; // be redundant compared to: int a; float b; // some weird syntax for MRVs [int, float] test() { return (1, 2f); } a, b =3D test(); // More prettiful Now, if struct could have reference members... int a; float b; struct { int a, float b} test() { return(1, 2f); } struct { ref a; ref b; } =3D test(); or: int a; float b; [int, float] test() { return(1, 2f); } [ref a, ref b] =3D test(); With all that said, I really like your proposal, and I hope it gets = implemented. -- Simen
Apr 14 2008
next sibling parent reply downs <default_357-line yahoo.de> writes:
Simen Kjaeraas wrote:
 On Mon, 14 Apr 2008 11:23:50 +0200, downs <default_357-line yahoo.de>
 wrote:
 
 Let's give this another try.
 The following proposal has the advantage that it's funded mostly on
 existing syntax.

 An anonymous struct, in the position where you'd normally expect a
 function/method return type, is usable as the return type instead.

 Example:

 struct { int a; float b; } test() { return(1, 2f); }

 writefln(test().a, test().b);

 The compiler would translate this into "current D" as follows:

 struct _D_anonymous_struct_1 { int a; float b; }
 _D_anonymous_struct_1 test() { return _D_anonymous_struct_1(1, 2f); }

 Because of the not-exactly-clear type name, it is necessary to store
 the returned value in an auto/const/static variable.

 This looks like it could be ambiguous, but it really isn't - the two
 conditions required here - an unnamed struct in the position where a
 return type would be expected - are quite unambiguous :)

 Whaddya think?

  --downs
Looks pretty good - there are reasons to allow returning anonymous structs, and I'm sure they could find uses in other places as well. One problem I see is that, compared to 'true' MRV, it requires extra assignments if you want the values outside the struct. int a; float b; struct { int a; float b; } test() { return(1, 2f); } auto result = test(); a = result.a; // These should b = result.b; // be redundant compared to: int a; float b; // some weird syntax for MRVs [int, float] test() { return (1, 2f); } a, b = test(); // More prettiful
Well, I see two ways around that .. the first is "with (test()) { use a and b here; }" the second is to allow mixins to work on non-templates, so you could mixin test() to get a and b in the current scope. the third is to use some type of struct variable holder using pointers, that allows assignment from same-layout other-type structs so, int a; float b; ptuple(a, b) = test(); // this could work in current D
 Now, if struct could have reference members...
 
   int a;
   float b;
 
   struct { int a, float b} test() { return(1, 2f); }
 
   struct { ref a; ref b; } = test();
 
 or:
 
   int a;
   float b;
 
   [int, float] test() { return(1, 2f); }
 
   [ref a, ref b] = test();
 
 
 With all that said, I really like your proposal, and I hope it gets
 implemented.
 
 -- Simen
Yay, thanks! :D --downs
Apr 14 2008
parent downs <default_357-line yahoo.de> writes:
downs wrote:
 Well, I see two ways around that ..
 
 the first is "with (test()) { use a and b here; }"
 
 the second is to allow mixins to work on non-templates, so you could mixin
test() to get a and b in the current scope.
 
 the third is
Three, three ways. Our three ways of MRV are with, mixin and
 to use some type of struct variable holder using pointers, that allows
assignment from same-layout other-type structs
the fourth is .. I'll come in again. :hasty exit:
Apr 14 2008
prev sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Simen Kjaeraas wrote:
 On Mon, 14 Apr 2008 11:23:50 +0200, downs <default_357-line yahoo.de> 
 wrote:
 
 Let's give this another try.
 The following proposal has the advantage that it's funded mostly on 
 existing syntax.

 An anonymous struct, in the position where you'd normally expect a 
 function/method return type, is usable as the return type instead.

 Example:

 struct { int a; float b; } test() { return(1, 2f); }

 writefln(test().a, test().b);

 The compiler would translate this into "current D" as follows:

 struct _D_anonymous_struct_1 { int a; float b; }
 _D_anonymous_struct_1 test() { return _D_anonymous_struct_1(1, 2f); }

 Because of the not-exactly-clear type name, it is necessary to store 
 the returned value in an auto/const/static variable.

 This looks like it could be ambiguous, but it really isn't - the two 
 conditions required here - an unnamed struct in the position where a 
 return type would be expected - are quite unambiguous :)

 Whaddya think?

  --downs
Looks pretty good - there are reasons to allow returning anonymous structs, and I'm sure they could find uses in other places as well. One problem I see is that, compared to 'true' MRV, it requires extra assignments if you want the values outside the struct.
Hmm, yeh, I didn't take the proposal to be a replacement for other more Tuple-ish MRV discussions. It only makes sense to use structs if you care about given names to the elements. If you don't care about having named elements, like a,b = get_minmax(); then a tuple-based solution makes more sense. That's why I was asking if he actually needed that. I meant did he really need multiple return values where the values were named, and not anonymous like in a Tuple. --bb
Apr 14 2008
prev sibling next sibling parent reply Extrawurst <spam extrawurst.org> writes:
downs schrieb:
 Let's give this another try.
 The following proposal has the advantage that it's funded mostly on existing
syntax.

 An anonymous struct, in the position where you'd normally expect a
function/method return type, is usable as the return type instead.

 Example:

 struct { int a; float b; } test() { return(1, 2f); }

 writefln(test().a, test().b);

 The compiler would translate this into "current D" as follows:

 struct _D_anonymous_struct_1 { int a; float b; }
 _D_anonymous_struct_1 test() { return _D_anonymous_struct_1(1, 2f); }

 Because of the not-exactly-clear type name, it is necessary to store the
returned value in an auto/const/static variable.

 This looks like it could be ambiguous, but it really isn't - the two
conditions required here - an unnamed struct in the position where a return
type would be expected - are quite unambiguous :)

 Whaddya think?

  --downs
   
What speaks against solving the MRV issue by allowing tuples(TypeTuple) as return types ? I would love to see that..
Apr 14 2008
parent reply downs <default_357-line yahoo.de> writes:
Extrawurst wrote:
 What speaks against solving the MRV issue by allowing tuples(TypeTuple)
 as return types ? I would love to see that..
Well yeah, me too :) but this is probably easier to implement, and as such, has a higher chance of actually _happening_. (Tuple MRV was proposed before) --downs
Apr 14 2008
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"downs" <default_357-line yahoo.de> wrote in message 
news:ftvci0$2iep$1 digitalmars.com...
 Extrawurst wrote:
 What speaks against solving the MRV issue by allowing tuples(TypeTuple)
 as return types ? I would love to see that..
Well yeah, me too :) but this is probably easier to implement, and as such, has a higher chance of actually _happening_. (Tuple MRV was proposed before) --downs
Easier to implement? Think about it: what's the difference between a struct and a tuple? <_<
_>
(Hint: not a whole lot) And this is something I'd like to see explored in a few more areas than just MRVs ;)
Apr 14 2008
prev sibling next sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
downs, el 14 de abril a las 11:23 me escribiste:
 Let's give this another try.
 The following proposal has the advantage that it's funded mostly on existing
syntax.
 
 An anonymous struct, in the position where you'd normally expect a
function/method return type, is usable as the return type instead.
 
 Example:
 
 struct { int a; float b; } test() { return(1, 2f); }
 
 writefln(test().a, test().b);
I think what you really want here is to return a tuple. I think adding tuples to the language/library would be much more elegant. For example: (int, float) test() { return (1, 2f); } writefln(test()[0], test()[1]); (I know the syntax it's no good, I wanted just to expose the concept). -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- Vaporeso, al verse enfundado por la depresión, decide dar fin a su vida tomando Chinato Garda mezclado con kerosene al 50%. Ante el duro trance pierde la movilidad en sus miembros derechos: inferior y superior. En ese momento es considerado como el hombre líder del movimiento de izquierda de Occidente.
Apr 14 2008
parent "Hans W. Uhlig" <huhlig gmail.com> writes:
Leandro Lucarella wrote:
 downs, el 14 de abril a las 11:23 me escribiste:
 Let's give this another try.
 The following proposal has the advantage that it's funded mostly on existing
syntax.

 An anonymous struct, in the position where you'd normally expect a
function/method return type, is usable as the return type instead.

 Example:

 struct { int a; float b; } test() { return(1, 2f); }

 writefln(test().a, test().b);
I think what you really want here is to return a tuple. I think adding tuples to the language/library would be much more elegant. For example: (int, float) test() { return (1, 2f); } writefln(test()[0], test()[1]); (I know the syntax it's no good, I wanted just to expose the concept).
I think adding them to the core of the language would be better then making a library hack.
Apr 18 2008
prev sibling next sibling parent Tower Ty <tytower hotmail.com> writes:
downs Wrote:

 Let's give this another try.
 The following proposal has the advantage that it's funded mostly on existing
syntax.
 
 An anonymous struct, in the position where you'd normally expect a
function/method return type, is usable as the return type instead.
 
 Example:
 
 struct { int a; float b; } test() { return(1, 2f); }
 
 writefln(test().a, test().b);
 
 The compiler would translate this into "current D" as follows:
 
 struct _D_anonymous_struct_1 { int a; float b; }
 _D_anonymous_struct_1 test() { return _D_anonymous_struct_1(1, 2f); }
 
 Because of the not-exactly-clear type name, it is necessary to store the
returned value in an auto/const/static variable.
 
 This looks like it could be ambiguous, but it really isn't - the two
conditions required here - an unnamed struct in the position where a return
type would be expected - are quite unambiguous :)
 
 Whaddya think?
 
  --downs
Whaddya think? -It wold be nice to be able to read it in plain english "it's funded mostly on existing syntax" -funded means we are using money "ot-exactly-clear "- err not really sure ? "auto/const/static variable"- this must be a new type of multi-variable ?
Apr 14 2008
prev sibling next sibling parent reply Georg Wrede <georg nospam.org> writes:
downs wrote:
 Let's give this another try. The following proposal has the advantage
 that it's funded mostly on existing syntax.
 
 An anonymous struct, in the position where you'd normally expect a
 function/method return type, is usable as the return type instead.
An interesting idea.
 Example:
 
 struct { int a; float b; } test() { return(1, 2f); }
 
 writefln(test().a, test().b);
 
 The compiler would translate this into "current D" as follows:
 
 struct _D_anonymous_struct_1 { int a; float b; } 
 _D_anonymous_struct_1 test() { return _D_anonymous_struct_1(1, 2f); }
One might use this especially with inner functions, where the entire scope fits on screen. But still, the concept of MRV is much larger, and to make decent use of MRV, the language would have to have many other facilities, IMHO.
Apr 14 2008
parent reply downs <default_357-line yahoo.de> writes:
Please, read the NG. The more powerful ()-based syntax has been brought up
before, and nothing ever came of it (there's some ambiguity with the comma
operator)

This time around, I chose a syntax that was intentionally based on existing
language features, precisely to sidestep those issues.

Imnsho, multiple return values are useful enough to warrant an implementation
even if we can't have full ()-based tuple assignment and returning support.

 --downs
Apr 14 2008
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
downs wrote:
 Please, read the NG. The more powerful ()-based syntax has been brought up
before, and nothing ever came of it (there's some ambiguity with the comma
operator)
 
 This time around, I chose a syntax that was intentionally based on existing
language features, precisely to sidestep those issues.
 
 Imnsho, multiple return values are useful enough to warrant an implementation
even if we can't have full ()-based tuple assignment and returning support.
 
  --downs
You're talking about just bare parentheses right? That's not the only option. Right now from what I understand Tuple!(int,float) can be a return value from a D2 function. So the question is just can we make a nicer way to write Tuple!(int, float) that isn't ambiguous. You just need something to disambiguate out in front. Like maybe (int,float) --bb
Apr 14 2008
parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 15/04/2008, Bill Baxter <dnewsgroup billbaxter.com> wrote:
 Right now from what I understand Tuple!(int,float) can be a return
 value from a D2 function.
Providing you import std.typecons, yes. There is an unfortunate ambiguity in the D docs about what a Tuple is. (http://digitalmars.com/d/2.0/tuple.html conflicts with http://digitalmars.com/d/2.0/phobos/std_typecons.html). I have submitted a bugzilla report about that. Anyway, a std.typecons.Tuple is what you want. That's the one that can be a return value from a D2 function.
Apr 14 2008
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Janice Caron wrote:
 On 15/04/2008, Bill Baxter <dnewsgroup billbaxter.com> wrote:
 Right now from what I understand Tuple!(int,float) can be a return
 value from a D2 function.
Providing you import std.typecons, yes. There is an unfortunate ambiguity in the D docs about what a Tuple is. (http://digitalmars.com/d/2.0/tuple.html conflicts with http://digitalmars.com/d/2.0/phobos/std_typecons.html). I have submitted a bugzilla report about that. Anyway, a std.typecons.Tuple is what you want. That's the one that can be a return value from a D2 function.
Oh.... I see. That's just a struct tuple with a bunch of ctfe code gen inside. Dang. I thought Walter had made D2 able to return "classic" Tuples. Oh well. The doc string has a great example ddoc at it's finest: """ """ Great. You have to run it through ddoc and a browser just to to find out what the heck the mystery shortcut notation is. --bb
Apr 15 2008
prev sibling parent reply Clay Smith <clayasaurus gmail.com> writes:
downs wrote:
 Let's give this another try.
 The following proposal has the advantage that it's funded mostly on existing
syntax.
 
 An anonymous struct, in the position where you'd normally expect a
function/method return type, is usable as the return type instead.
 
 Example:
 
 struct { int a; float b; } test() { return(1, 2f); }
 
 writefln(test().a, test().b);
 
 The compiler would translate this into "current D" as follows:
 
 struct _D_anonymous_struct_1 { int a; float b; }
 _D_anonymous_struct_1 test() { return _D_anonymous_struct_1(1, 2f); }
 
 Because of the not-exactly-clear type name, it is necessary to store the
returned value in an auto/const/static variable.
 
 This looks like it could be ambiguous, but it really isn't - the two
conditions required here - an unnamed struct in the position where a return
type would be expected - are quite unambiguous :)
 
 Whaddya think?
 
  --downs
If there is MRV I don't see why not take the python route and support tuples. ~ Clay
Apr 14 2008
parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 15/04/2008, Clay Smith <clayasaurus gmail.com> wrote:
  If there is MRV I don't see why not take the python route and support
 tuples.
I agree. Particularly as we already have tuples (std.typecons.Tuple), so really all that we need now is a little bit of syntactic sugar. Something like: BEFORE import std.typecons Tuple!(int,float) test() { return Tuple!(int,float)(1,2); } auto t = test(); int a = t._0; float b = t._1; AFTER: {int,float} test() { return {1,2f}; } {a,b} = test(); or similar. The implementation can still be in std.typecons, but the compiler could save you a bit of typing. Incidently, std.typecons.Tuple can already name the fields. Tuple!(int,"a",float,"b"} is basically the same thing as struct anon { int a; float b; } but most of the time, there's little need to name the fields, as _0, _1 etc. suffice, and if we add some syntactic sugar, we won't even need those.
Apr 15 2008
parent reply Extrawurst <spam extrawurst.org> writes:
Janice Caron schrieb:
 On 15/04/2008, Clay Smith <clayasaurus gmail.com> wrote:
   
  If there is MRV I don't see why not take the python route and support
 tuples.
     
I agree. Particularly as we already have tuples (std.typecons.Tuple), so really all that we need now is a little bit of syntactic sugar. Something like: BEFORE import std.typecons Tuple!(int,float) test() { return Tuple!(int,float)(1,2); } auto t = test(); int a = t._0; float b = t._1; AFTER: {int,float} test() { return {1,2f}; } {a,b} = test(); or similar. The implementation can still be in std.typecons, but the compiler could save you a bit of typing. Incidently, std.typecons.Tuple can already name the fields. Tuple!(int,"a",float,"b"} is basically the same thing as struct anon { int a; float b; } but most of the time, there's little need to name the fields, as _0, _1 etc. suffice, and if we add some syntactic sugar, we won't even need those.
First of all, returning Tuples with whatever syntax must be enabled, right ?
Apr 15 2008
next sibling parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 15/04/2008, Extrawurst <spam extrawurst.org> wrote:
  First of all, returning Tuples with whatever syntax must be enabled, right
 ?
I don't understand the question. What do you mean "enabled"? We already have tuples, right now. This is already valid, working, D:
    import std.typecons

    Tuple!(int,float) test()
    {
         return Tuple!(int,float)(1,2);
    }

    auto t = test();
    int a = t._0;
    float b = t._1;
The only question is whether or not the syntax can be improved.
Apr 15 2008
parent reply Extrawurst <spam extrawurst.org> writes:
Janice Caron schrieb:
 On 15/04/2008, Extrawurst <spam extrawurst.org> wrote:
   
  First of all, returning Tuples with whatever syntax must be enabled, right
 ?
     
I don't understand the question. What do you mean "enabled"? We already have tuples, right now. This is already valid, working, D:
Now i am really confused, i confused Tuple's and TypeTuple's cause returing a TypeTuple by a functions doesn't work. Where is the difference there anyway ? Why need both ? Why has the normal typecons.Tuple no []-op like the TypeTuple ?
Apr 15 2008
next sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Extrawurst wrote:
 Janice Caron schrieb:
 On 15/04/2008, Extrawurst <spam extrawurst.org> wrote:
  
  First of all, returning Tuples with whatever syntax must be enabled, 
 right
 ?
     
I don't understand the question. What do you mean "enabled"? We already have tuples, right now. This is already valid, working, D:
Now i am really confused, i confused Tuple's and TypeTuple's cause returing a TypeTuple by a functions doesn't work. Where is the difference there anyway ? Why need both ? Why has the normal typecons.Tuple no []-op like the TypeTuple ?
Because typecons Tuple is just a plain old struct. It happens to have some funky automatically generated members, but it's still just a plain old struct. I was misled too. It's not the Tuple you're looking for. You can go about your business. Move along. --bb
Apr 15 2008
prev sibling parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 15/04/2008, Extrawurst <spam extrawurst.org> wrote:
  Now i am really confused,
As is everyone
 i confused Tuple's and TypeTuple's cause returing
 a TypeTuple by a functions doesn't work.
 Where is the difference there
 anyway ?
Blame Walter for that. He used the word Tuple to mean something counterintuitive. Later, Andrei came along and wrote std.typecons, which uses the word Tuple correctly (i.e. the same way it's used in every other programming language under the sun).
 Why need both ?
We don't.
 Why has the normal typecons.Tuple no []-op like the
 TypeTuple ?
It's a different beast. You use it differently. The first ten fields may be accessed with ._0 to ._9. Any field may be accessed as .field[n]. Any /named/ field may be accessed by name.
Apr 15 2008
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Janice Caron wrote:
 Later, Andrei came along and wrote std.typecons, which uses the word
 Tuple correctly (i.e. the same way it's used in every other
 programming language under the sun).
...  The first ten fields
 may be accessed with ._0 to ._9. Any field may be accessed as
 .field[n]. Any /named/ field may be accessed by name.
I don't recall tuples working like that in any language I've used. TypeTuples are much closer to what is called a tuple in other languages. TypeTuple!(int,float,string) x; x[0] = 3; x[1] = 2.5; x[2] = "hello"; writefln("x = ", x); writefln("type = ", typeof(x).stringof);
 x = 32.5hello
 type = (int, float, invariant(char)[])
Ok, the way it prints is odd, but that's pretty much what most languages call a tuple. That's what they're like in ML and Python at least, which is where I've seen 'em. They aren't structs pretending to be tuples. They're actual tuples. An ordered, fixed-sized list of anonymous items of fixed, but arbitrary type. As for the weird printing, that's really the fault of automatic flattening of tuples. That was probably a bad idea. Users should have to do something to explode a tuple to make it act like a list of arguments. The other thing TypeTuple lacks is a literal value syntax. You can only initialize them one-by-one like that. Or by creating a struct and using .tupleof on it. Which means you can use the /other/ Tuple for that if you define the type first: struct S {int a;float b;string c;} S s = S(101,3.14,"bye"); x = s.tupleof; or alias Tuple!(int,float,string) T; // [1] T t = T(451,2.718,"struct"); x = t.tupleof; My opinion is that it's Andrei who's abusing the terminology by calling a struct that pretends to be a tuple a Tuple. [1] actually that doesn't work. Known bug? The example in the documentation: alias Tuple!(string, string) DicEntry; // names can be omitted doesn't compile either. (Dmd 2.012) --bb
Apr 15 2008
parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 15/04/2008, Bill Baxter <dnewsgroup billbaxter.com> wrote:
  TypeTuples are much closer to what is called a tuple in other languages.

     TypeTuple!(int,float,string) x;
     x[0] = 3;
     x[1] = 2.5;
     x[2] = "hello";
Where is TypeTuple! defined?
 An ordered, fixed-sized list of anonymous items of fixed,
 but arbitrary type.
Yep, that's a std.typecons.Tuple. A "Walter Tuple" is a list of arbitrary values and types, for example ( int, float, 42, "hello" ). An "Andrei Tuple" is an ordered, fixed-sized list of items of fixed but arbitrary type. (Andrei also lets you name some or all of the items if you want, so they don't /have/ to be anonymous, but naming the fields is optional. Think of that as an extra bonus feature).
Apr 15 2008
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Janice Caron wrote:
 On 15/04/2008, Bill Baxter <dnewsgroup billbaxter.com> wrote:
  TypeTuples are much closer to what is called a tuple in other languages.

     TypeTuple!(int,float,string) x;
     x[0] = 3;
     x[1] = 2.5;
     x[2] = "hello";
Where is TypeTuple! defined?
std.typetuple It's just the classic "Walter tuple" as you put it though. Just called TypeTuple.
 An ordered, fixed-sized list of anonymous items of fixed,
 but arbitrary type.
Yep, that's a std.typecons.Tuple.
Except the anonymous part. And the list part. Lists use [i] for indexing, not something weird like .field!(i). ((But this is D so I should have said "array" rather than "list", I guess))
 A "Walter Tuple" is a list of arbitrary values and types, for example
 ( int, float, 42, "hello" ).
But that won't compile in places where a type is needed, or where a value is needed. Just like "int x = float;" won't compile. Doesn't seem a problem.
 An "Andrei Tuple" is an ordered, fixed-sized list of items of fixed
 but arbitrary type.
An "Andrei Tuple" is a struct. So if you want to define structs to be tuples, then I guess that's your prerogative. I don't mean they are like structs, I mean they *are* structs. The definition is struct Tuple(T...) { // bunch of string mixins to automatically // generate member names from types in T } It's nifty as a workaround for lack of real, usable tuples, but that's all it is. So there's really no such thing as an anonymous element of an Andrei Tuple. It's a struct, so they all have names, just not names you gave them. Some other things that I would not expect of a real tuple: * is(AndreTuple == struct) returns true. * cannot slice it (except maybe with the likes of AndreiTuple.tupleof[1..$]) * __traits(allMembers,AndreiTuple) introspection reveals a lot of cruft like [_0 field _1 toString __T9tupleImplVi0TiTfZ] One advantage AndreiTuples do have is that they can be nested without the dreaded automatic flattening. At least I assume they can, since they're just structs. But nesting is good. So really I suspect what we'd all like is a combination of aspects of "Walter Tuples" and "Andrei Tuples". --bb
Apr 15 2008
prev sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 15/04/2008, Janice Caron <caron800 googlemail.com> wrote:
 This is already valid, working, D:

    import std.typecons

    Tuple!(int,float) test()
    {
         return Tuple!(int,float)(1,2);
    }

    auto t = test();
    int a = t._0;
    float b = t._1;
Hey, we're getting there! Here's something I missed. The return statement above could have been rewritten as: return tuple(1,2f); which is much more convenient.
Apr 24 2008