D - Other Modern Features
- Mark Brudnak (58/58) Nov 26 2003 I am very new to the D language and have not dug in too deep either. I ...
- Walter (9/66) Nov 28 2003 Thanks! Glad you're here.
- Matthew Wilson (3/17) Nov 28 2003 Most definitely
- Charles Sanders (11/90) Nov 28 2003 Boost has accomplished these 'tuples' through some template magic, perha...
- Mark Brudnak (19/24) Nov 28 2003 language
- Berin Loritsch (7/29) Dec 01 2003 Honestly, I have not even thought about a feature like this... Practlic...
- Mark J. Brudnak (67/73) Dec 01 2003 Perhaps, but presumably, you could overload a function based on its retu...
- Berin Loritsch (11/46) Dec 01 2003 ... Runs away screamming ... NOOOOOO!!!!!
- Mark Brudnak (15/25) Dec 01 2003 you are
- Berin Loritsch (3/57) Dec 02 2003 Agreed. However, please don't make it look like an overloaded method th...
- Felix (8/54) Dec 01 2003 Some other issues on the multiple params return:
- Felix (6/85) Dec 01 2003 Yeah, maybe the multiple outputs would be a nice feature. However, the i...
- Mark J. Brudnak (67/73) Dec 01 2003 Perhaps you could overload a function based on its return
-
Berin Loritsch
(4/38)
Dec 01 2003
- Steve Maillet (14/18) Dec 25 2003 While it may be a few keystrokes more compact it's hardly easier to read...
- Mark Brudnak (43/61) Dec 25 2003 There are two different issues being discussed in this thread, the first...
- Steve Maillet (10/10) Dec 30 2003 "(x, y) = (y, x) ; /* simple, clear, concise */"
- Matthew (16/22) Dec 30 2003 templates
- Matthew Wilson (5/9) Nov 28 2003 language
- Ilya Minkov (5/7) Nov 29 2003 With explicit intantiation we're probably back at custom return structs....
- Felix (11/21) Dec 01 2003 Just a thought: I work in Matlab so I use the multiple return parameters...
- Mark J. Brudnak (23/50) Dec 01 2003 The syntax should be:
- Makaan Kublai Kahn (38/97) Dec 01 2003 You can already do this. You can return a struct I in C and C++.
- Mark J. Brudnak (60/97) Dec 01 2003 return
- Georg Wrede (39/45) Dec 01 2003 Functions returning several values could be used like
- Ben Hinkle (9/18) Dec 01 2003 MATLAB allows both a variable number of inputs and outputs. It does this...
- Mark Brudnak (11/20) Dec 01 2003 be
- brad beveridge (18/56) Dec 01 2003 How would multiple returns work if you don't provide places for the
- Mark Brudnak (13/69) Dec 01 2003 A call would look like this.
- Sarat Venugopal (37/57) Dec 02 2003 Two possibilities:
- Steve Maillet (11/11) Dec 25 2003 What's good for MATLAB is not necessarily good for D. These are two VERY
- Mark Brudnak (31/43) Dec 25 2003 Agreed!
- davepermen (3/5) Dec 26 2003 so all of your functions only have one parameter as well? because this m...
- Steve Maillet (14/14) Dec 30 2003 You are comparing apples to oranges the mathematical definition of a
- qw (14/19) Dec 30 2003 Why would
- Steve Maillet (12/16) Dec 31 2003 It wouldn't - both versions of the syntax, quite frankly, suck.
- Lewis (26/48) Dec 31 2003 that would be very nice, as thats whats im used to also. You should defi...
- Steve Maillet (43/43) Dec 31 2003 "You could think of multiple return as returning a composite object (tup...
- Ilya Minkov (13/14) Jan 01 2004 Yup. and there are tuples in boost.
- Mark Brudnak (70/116) Jan 01 2004 (tuple)"
- Mark Brudnak (22/60) Dec 01 2003 We should crawl before we walk or run. I think a nice start would be to
- Antti =?iso-8859-1?Q?Syk=E4ri?= (50/71) Dec 03 2003 I must ask, how would a statement like the second one be implemented?
- Mark Brudnak (17/49) Dec 04 2003 This would be legal, because the tuple-operator (,,,,,) would have *high...
- Commander Odama (10/129) Dec 06 2003 With structs but you have the advantage of selecting whatever value you ...
- Sean L. Palmer (16/25) Dec 07 2003 I currently think it's a good idea to unify structs and parameter lists,...
- Ilya Minkov (32/41) Dec 07 2003 This would requiere big changes in the language. Let the fields rather
- Sean L. Palmer (61/95) Dec 07 2003 and
- Dan Liebgold (8/12) Dec 08 2003 can't
- Mark Brudnak (20/128) Dec 09 2003 Also note that if tuples are entities on their own, then they can be bot...
- Heretic (2/13) Dec 02 2003 How bout this: (a) = someFunc( (int, int, int) = foo(float) ) ?
I am very new to the D language and have not dug in too deep either. I am impressed with what I have seen so far. Since D is still under developmet, I would like to know if D has the following features. If not, then the plasuability of incorporating them at some point in the future. 1) Multiple return values (like Matlab) eg. (float[] data, string name, string unit) = getChannel(DataFile file, int chanNo) ; This would eliminate alot a repetitive coding. Also, as an option, the compiler could force all LHS args to be 'outs' and RHS args to be 'ins'. 2) Variable argument lists for the caller and callee with type information automatically attached. eg. CALLER: delegate myDelegate = func ; . . . param[] args ; args ~= 1.0 ; args ~= "hello" ; myDelegate(args) ; CALLEE: /* I throw an exception if types do not match */ func(float a, string message) { /* do something */ } eg. CALLER: func2("albert", 1916, "GR") ; CALLEE: func2( param[] args) { switch (args[0].type) { case int: /*etc */ } } eg. Use variable argument lists on LHS too. CALLER: (param[] outArgs) = myDelegate(param[] inArgs) ; CALLEE: (param[] outArgs) = func(param[] inArgs) { param[] myRetVals ; . . . myRetvals ~= result1 ; myRetvals ~= result2 ; return (myRetVals) ; } 3) Native support for plugin modules. Allow plugin overloading. eg. myPict = openPicture("lion.gif") ; display(hWind, myPict) ; This call is to an abstract proxy class which when called searches and catalogues all available plugins which have the proper interface. It asks each if it can successfully handle the case passed to the abstract proxy class (eg. can you open a GIF?). If it can, then it loads the plugin, instantiates the concrete derived class and returns a reference to it. All subsequent calls are handled directly by the plugin. Thank you, Mark
Nov 26 2003
"Mark Brudnak" <malibrud provide.net> wrote in message news:bq3scc$28tl$1 digitaldaemon.com...I am very new to the D language and have not dug in too deep either. I am impressed with what I have seen so far.Thanks! Glad you're here.Since D is still under developmet, I would like to know if D has the following features. If not, then the plasuability of incorporating them at some point in the future. 1) Multiple return values (like Matlab) eg. (float[] data, string name, string unit) = getChannel(DataFile file, int chanNo) ; This would eliminate alot a repetitive coding. Also, as an option,thecompiler could force all LHS args to be 'outs' and RHS args to be 'ins'.No. But it does have 'out' parameters, which does much the same thing.2) Variable argument lists for the caller and callee with type information automatically attached. eg. CALLER: delegate myDelegate = func ; . . . param[] args ; args ~= 1.0 ; args ~= "hello" ; myDelegate(args) ; CALLEE: /* I throw an exception if types do not match */ func(float a, string message) { /* do something */ } eg. CALLER: func2("albert", 1916, "GR") ; CALLEE: func2( param[] args) { switch (args[0].type) { case int: /*etc */ } } eg. Use variable argument lists on LHS too. CALLER: (param[] outArgs) = myDelegate(param[] inArgs) ; CALLEE: (param[] outArgs) = func(param[] inArgs) { param[] myRetVals ; . . . myRetvals ~= result1 ; myRetvals ~= result2 ; return (myRetVals) ; }No. There's been a lot of discussion about this, though.3) Native support for plugin modules. Allow plugin overloading. eg. myPict = openPicture("lion.gif") ; display(hWind, myPict) ; This call is to an abstract proxy class which when called searches and catalogues all available plugins which have the proper interface. It asks each if it can successfully handle the case passed to the abstract proxy class (eg. can you open a GIF?). If it can, then it loads theplugin,instantiates the concrete derived class and returns a reference to it.Allsubsequent calls are handled directly by the plugin.That seems like it would be a library feature. Would you care to write one?
Nov 28 2003
searches3) Native support for plugin modules. Allow plugin overloading. eg. myPict = openPicture("lion.gif") ; display(hWind, myPict) ; This call is to an abstract proxy class which when calledItand catalogues all available plugins which have the proper interface.Most definitelyasks each if it can successfully handle the case passed to the abstract proxy class (eg. can you open a GIF?). If it can, then it loads theplugin,instantiates the concrete derived class and returns a reference to it.Allsubsequent calls are handled directly by the plugin.That seems like it would be a library feature.
Nov 28 2003
Boost has accomplished these 'tuples' through some template magic, perhaps the same can be done with D, although i agree I would LOVE to see a language that implemented this. C "Walter" <walter digitalmars.com> wrote in message news:bq8rtf$l6o$1 digitaldaemon.com...1) Multiple return values (like Matlab)"Mark Brudnak" <malibrud provide.net> wrote in message news:bq3scc$28tl$1 digitaldaemon.com...amI am very new to the D language and have not dug in too deep either. Iinformationimpressed with what I have seen so far.Thanks! Glad you're here.Since D is still under developmet, I would like to know if D has the following features. If not, then the plasuability of incorporating them at some point in the future. 1) Multiple return values (like Matlab) eg. (float[] data, string name, string unit) = getChannel(DataFile file, int chanNo) ; This would eliminate alot a repetitive coding. Also, as an option,thecompiler could force all LHS args to be 'outs' and RHS args to be 'ins'.No. But it does have 'out' parameters, which does much the same thing.2) Variable argument lists for the caller and callee with typesearchesautomatically attached. eg. CALLER: delegate myDelegate = func ; . . . param[] args ; args ~= 1.0 ; args ~= "hello" ; myDelegate(args) ; CALLEE: /* I throw an exception if types do not match */ func(float a, string message) { /* do something */ } eg. CALLER: func2("albert", 1916, "GR") ; CALLEE: func2( param[] args) { switch (args[0].type) { case int: /*etc */ } } eg. Use variable argument lists on LHS too. CALLER: (param[] outArgs) = myDelegate(param[] inArgs) ; CALLEE: (param[] outArgs) = func(param[] inArgs) { param[] myRetVals ; . . . myRetvals ~= result1 ; myRetvals ~= result2 ; return (myRetVals) ; }No. There's been a lot of discussion about this, though.3) Native support for plugin modules. Allow plugin overloading. eg. myPict = openPicture("lion.gif") ; display(hWind, myPict) ; This call is to an abstract proxy class which when calledItand catalogues all available plugins which have the proper interface.one?asks each if it can successfully handle the case passed to the abstract proxy class (eg. can you open a GIF?). If it can, then it loads theplugin,instantiates the concrete derived class and returns a reference to it.Allsubsequent calls are handled directly by the plugin.That seems like it would be a library feature. Would you care to write
Nov 28 2003
"Charles Sanders" <sanders-consulting comcast.net> wrote in message news:bq8vs3$qos$1 digitaldaemon.com...languageBoost has accomplished these 'tuples' through some template magic, perhaps the same can be done with D, although i agree I would LOVE to see a1) Multiple return values (like Matlab)that implemented this. Cis not new and I think that semantically it is cleaner than in, out, inout. For complicated function calls with multiple ins and outs I usually define an in-structure and out-structure to facilitate same thing. This however forces the declaration, allocation and stuffing/unstuffing on the part of the caller and callee (a lot of extra code). For functions which return two or three values, this is overkill. In these cases I have seen functions which return one value, be modified to return two values, one by value, one by reference. i.e. myResult = calculateIt( x, y, z) ; becomes: myResult = calculateIt(x, y, z, t, &anotherResult) ; /* easiest path to add another out */ with multiple return values the code would likely grow as follows myResult = calculateIt( x, y, z) ; becomes: (myResult, anotherResult) = calculateIt(x, y, z, t) ; /* much better ! */
Nov 28 2003
Mark Brudnak wrote:is not new and I think that semantically it is cleaner than in, out, inout. For complicated function calls with multiple ins and outs I usually define an in-structure and out-structure to facilitate same thing. This however forces the declaration, allocation and stuffing/unstuffing on the part of the caller and callee (a lot of extra code). For functions which return two or three values, this is overkill. In these cases I have seen functions which return one value, be modified to return two values, one by value, one by reference. i.e. myResult = calculateIt( x, y, z) ; becomes: myResult = calculateIt(x, y, z, t, &anotherResult) ; /* easiest path to add another out */ with multiple return values the code would likely grow as follows myResult = calculateIt( x, y, z) ; becomes: (myResult, anotherResult) = calculateIt(x, y, z, t) ; /* much better ! */Honestly, I have not even thought about a feature like this... Practlically speaking, how would you call such a beast in the client code? (foo, bar) = calculateIt( x, y, z, t ); and if we wanted to explicitly ignore a value: (,bar) = calculateIt( x, y, z, t ); ???
Dec 01 2003
"Berin Loritsch" <bloritsch d-haven.org> wrote in messageHonestly, I have not even thought about a feature like this...Practlicallyspeaking, how would you call such a beast in the client code? (foo, bar) = calculateIt( x, y, z, t ); and if we wanted to explicitly ignore a value: (,bar) = calculateIt( x, y, z, t ); ???Perhaps, but presumably, you could overload a function based on its return parameter list as well as its argument list. For example class MyClass { int func( int x, int y, int z) { int result ; /* do stuff */ return result ; } (int, float) func( int x, int y, int z) { float bar ; int ibar = func(x, y, z) ; /* do stuff */ return ( ibar, bar ) ; } } Ignoring return parameters may be something necessary however. I would say that they are analogous to default arguments (like C++). Of course it would be difficult to determine which return value one may wish to ignore, so requiring that all ignorable return parameters appear at the end of the parameter list is a bit restrictive. An alternative syntax for ignoring return parameters would be using the null keyword (is 'null' a key word in D?). For example, MyClass me = new MyClass ; int ibar; float bar ; (ibar, null) = me.func(1.0, 2.0, 3.0) ; /* or */ (null, bar) = me.func(1.0, 2.0, 3.0) ; /* or */ (ibar, bar) = me.func(1.0, 2.0, 3.0) ; Another alternative is to use named parameters. (I saw some discussion about this.) For example class MyClass { (int a, float b) func( int x, int y, int z) { float bar ; int ibar ; /* do stuff */ return ( ibar, bar ) ; } } MyClass me = new MyClass ; int ibar; float bar ; (a:ibar) = me.func(1.0, 2.0, 3.0) ; /* or */ (b:bar) = me.func(1.0, 2.0, 3.0) ; /* or */ (a:ibar, b:bar) = me.func(1.0, 2.0, 3.0) ; /* or just */ (ibar, bar) = me.func(1.0, 2.0, 3.0) ; This whole discussion however raises a larger issue. That is, what we are really discussing is expanding and generalizing what an lvalue and rvalue can and should be. For example if an lvalue was allowed to take the form of a parameter list, then the multiple return would be almost free. For example, a parameter list lvalue (and rvalue) would result in statements such as: (x, y) = (r*cos(theta), r*sin(theta)) ; /* which is more compact than.. */ x = r*cos(theta) ; y = r*sin(theta) ; which would function equivalent to the following function call, (x, y) = toCartesian( r, theta) ; /* which is more elegant (IMO) than */ toCartesian( r, theta, &x, &y) ; Mark.
Dec 01 2003
Mark J. Brudnak wrote:"Berin Loritsch" <bloritsch d-haven.org> wrote in message... Runs away screamming ... NOOOOOO!!!!! When the only difference between two functions is the return parameter, you are inviting disaster. How can you guarantee in what context which of the two methods are called? I personally would not want to maintain an application which uses such a construct, and it is explicitly forbidden in other languages. I think for a good reasons. It's a stretch for me just to accept multiple return values--when you throw in differing methods based on return type, things get really messy really fast. Please don't do such a thing.Honestly, I have not even thought about a feature like this...Practlicallyspeaking, how would you call such a beast in the client code? (foo, bar) = calculateIt( x, y, z, t ); and if we wanted to explicitly ignore a value: (,bar) = calculateIt( x, y, z, t ); ???Perhaps, but presumably, you could overload a function based on its return parameter list as well as its argument list. For example class MyClass { int func( int x, int y, int z) { int result ; /* do stuff */ return result ; } (int, float) func( int x, int y, int z) { float bar ; int ibar = func(x, y, z) ; /* do stuff */ return ( ibar, bar ) ; } }
Dec 01 2003
"Berin Loritsch" <bloritsch d-haven.org> wrote... Runs away screamming ... NOOOOOO!!!!!It is OK, you can run back, please.When the only difference between two functions is the return parameter,you areinviting disaster. How can you guarantee in what context which of the two methods are called?I agree.I personally would not want to maintain an application which uses such a construct, and it is explicitly forbidden in other languages. I think foragood reasons.So do I.It's a stretch for me just to accept multiple return values--when youthrow indiffering methods based on return type, things get really messy reallyfast.Please don't do such a thing.Three messages back in the thread you asked about how to ignore a value in the return parameters. The body of my reply enumerates some ideas that I had regarding ignoring return values, one of which was overloading on the return list. I think, if multiple return values were implemented, we should start with the simplest case (fixed return parameter lists) and let the laguage grow from there. The proper direction will not be known until people try the simple case.
Dec 01 2003
Agreed. However, please don't make it look like an overloaded method that only differs by return type. That would be an error IMNSHO. Mark Brudnak wrote:"Berin Loritsch" <bloritsch d-haven.org> wrote... Runs away screamming ... NOOOOOO!!!!!It is OK, you can run back, please.When the only difference between two functions is the return parameter,you areinviting disaster. How can you guarantee in what context which of the two methods are called?I agree.I personally would not want to maintain an application which uses such a construct, and it is explicitly forbidden in other languages. I think foragood reasons.So do I.It's a stretch for me just to accept multiple return values--when youthrow indiffering methods based on return type, things get really messy reallyfast.Please don't do such a thing.Three messages back in the thread you asked about how to ignore a value in the return parameters. The body of my reply enumerates some ideas that I had regarding ignoring return values, one of which was overloading on the return list. I think, if multiple return values were implemented, we should start with the simplest case (fixed return parameter lists) and let the laguage grow from there. The proper direction will not be known until people try the simple case.
Dec 02 2003
Some other issues on the multiple params return: - the values to ignore may be (,,usefulone,,,anotheruseful)=functie(etc1,etc2); -however, you will not be able anymore to call functie1(functie2(etc1,etc2)) and this will be a little clumsy: (v1,v2)=functie2(...); functie1(v1); But is something to think more seriously of it In article <bqfr31$1d2p$1 digitaldaemon.com>, Berin Loritsch says...Mark J. Brudnak wrote:"Berin Loritsch" <bloritsch d-haven.org> wrote in message... Runs away screamming ... NOOOOOO!!!!! When the only difference between two functions is the return parameter, you are inviting disaster. How can you guarantee in what context which of the two methods are called? I personally would not want to maintain an application which uses such a construct, and it is explicitly forbidden in other languages. I think for a good reasons. It's a stretch for me just to accept multiple return values--when you throw in differing methods based on return type, things get really messy really fast. Please don't do such a thing.Honestly, I have not even thought about a feature like this...Practlicallyspeaking, how would you call such a beast in the client code? (foo, bar) = calculateIt( x, y, z, t ); and if we wanted to explicitly ignore a value: (,bar) = calculateIt( x, y, z, t ); ???Perhaps, but presumably, you could overload a function based on its return parameter list as well as its argument list. For example class MyClass { int func( int x, int y, int z) { int result ; /* do stuff */ return result ; } (int, float) func( int x, int y, int z) { float bar ; int ibar = func(x, y, z) ; /* do stuff */ return ( ibar, bar ) ; } }
Dec 01 2003
Yeah, maybe the multiple outputs would be a nice feature. However, the issue of left-side parameters is a little special: they cannot bear an useful information for the function or they can? Usually when you pass func(&x) you may also give x an useful value. But, for programming simplicity, it would be a great enhancement. In article <bqfq35$1br4$1 digitaldaemon.com>, Mark J. Brudnak says..."Berin Loritsch" <bloritsch d-haven.org> wrote in messageHonestly, I have not even thought about a feature like this...Practlicallyspeaking, how would you call such a beast in the client code? (foo, bar) = calculateIt( x, y, z, t ); and if we wanted to explicitly ignore a value: (,bar) = calculateIt( x, y, z, t ); ???Perhaps, but presumably, you could overload a function based on its return parameter list as well as its argument list. For example class MyClass { int func( int x, int y, int z) { int result ; /* do stuff */ return result ; } (int, float) func( int x, int y, int z) { float bar ; int ibar = func(x, y, z) ; /* do stuff */ return ( ibar, bar ) ; } } Ignoring return parameters may be something necessary however. I would say that they are analogous to default arguments (like C++). Of course it would be difficult to determine which return value one may wish to ignore, so requiring that all ignorable return parameters appear at the end of the parameter list is a bit restrictive. An alternative syntax for ignoring return parameters would be using the null keyword (is 'null' a key word in D?). For example, MyClass me = new MyClass ; int ibar; float bar ; (ibar, null) = me.func(1.0, 2.0, 3.0) ; /* or */ (null, bar) = me.func(1.0, 2.0, 3.0) ; /* or */ (ibar, bar) = me.func(1.0, 2.0, 3.0) ; Another alternative is to use named parameters. (I saw some discussion about this.) For example class MyClass { (int a, float b) func( int x, int y, int z) { float bar ; int ibar ; /* do stuff */ return ( ibar, bar ) ; } } MyClass me = new MyClass ; int ibar; float bar ; (a:ibar) = me.func(1.0, 2.0, 3.0) ; /* or */ (b:bar) = me.func(1.0, 2.0, 3.0) ; /* or */ (a:ibar, b:bar) = me.func(1.0, 2.0, 3.0) ; /* or just */ (ibar, bar) = me.func(1.0, 2.0, 3.0) ; This whole discussion however raises a larger issue. That is, what we are really discussing is expanding and generalizing what an lvalue and rvalue can and should be. For example if an lvalue was allowed to take the form of a parameter list, then the multiple return would be almost free. For example, a parameter list lvalue (and rvalue) would result in statements such as: (x, y) = (r*cos(theta), r*sin(theta)) ; /* which is more compact than.. */ x = r*cos(theta) ; y = r*sin(theta) ; which would function equivalent to the following function call, (x, y) = toCartesian( r, theta) ; /* which is more elegant (IMO) than */ toCartesian( r, theta, &x, &y) ; Mark.
Dec 01 2003
"Berin Loritsch" <bloritsch d-haven.org> wrote >Honestly, I have not even thought about a feature like this...Practlicallyspeaking, how would you call such a beast in the client code? (foo, bar) = calculateIt( x, y, z, t ); and if we wanted to explicitly ignore a value: (,bar) = calculateIt( x, y, z, t ); ???Perhaps you could overload a function based on its return parameter list as well as its argument list. For example class MyClass { int func( int x, int y, int z) { int result ; /* do stuff */ return result ; } (int, float) func( int x, int y, int z) { float bar ; int ibar = func(x, y, z) ; /* do stuff */ return ( ibar, bar ) ; } } Ignoring return parameters may be something necessary however. I would say that they are analogous to default arguments (like C++). Of course it would be difficult to determine which return value one may wish to ignore, so requiring that all ignorable return parameters appear at the end of the parameter list is a bit restrictive. An alternative syntax for ignoring return parameters would be using the null keyword (is 'null' a key word in D?). For example, MyClass me = new MyClass ; int ibar; float bar ; (ibar, null) = me.func(1.0, 2.0, 3.0) ; /* or */ (null, bar) = me.func(1.0, 2.0, 3.0) ; /* or */ (ibar, bar) = me.func(1.0, 2.0, 3.0) ; Another alternative is to use named parameters. (I saw some discussion about this.) For example class MyClass { (int a, float b) func( int x, int y, int z) { float bar ; int ibar ; /* do stuff */ return ( ibar, bar ) ; } } MyClass me = new MyClass ; int ibar; float bar ; (a:ibar) = me.func(1.0, 2.0, 3.0) ; /* or */ (b:bar) = me.func(1.0, 2.0, 3.0) ; /* or */ (a:ibar, b:bar) = me.func(1.0, 2.0, 3.0) ; /* or just */ (ibar, bar) = me.func(1.0, 2.0, 3.0) ; This whole discussion however raises a larger issue. That is, what we are really discussing is expanding and generalizing what an lvalue and rvalue can and should be. For example if an lvalue was allowed to take the form of a parameter list, then the multiple return would be almost free. For example, a parameter list lvalue (and rvalue) would result in statements such as: (x, y) = (r*cos(theta), r*sin(theta)) ; /* which is more compact than.. */ x = r*cos(theta) ; y = r*sin(theta) ; which would function equivalent to the following function call, (x, y) = toCartesian( r, theta) ; /* which is more elegant (IMO) than */ toCartesian( r, theta, &x, &y) ; Mark.
Dec 01 2003
Mark J. Brudnak wrote:"Berin Loritsch" <bloritsch d-haven.org> wrote ><snip/> NOOO!!! Please see my previous posting on why not. It is a debug nightmare waiting to happen.Honestly, I have not even thought about a feature like this...Practlicallyspeaking, how would you call such a beast in the client code? (foo, bar) = calculateIt( x, y, z, t ); and if we wanted to explicitly ignore a value: (,bar) = calculateIt( x, y, z, t ); ???Perhaps you could overload a function based on its return parameter list as well as its argument list. For example class MyClass { int func( int x, int y, int z) { int result ; /* do stuff */ return result ; } (int, float) func( int x, int y, int z) { float bar ; int ibar = func(x, y, z) ; /* do stuff */ return ( ibar, bar ) ; } }
Dec 01 2003
(x, y) = (r*cos(theta), r*sin(theta)) ;While it may be a few keystrokes more compact it's hardly easier to read or comprehend. Many moons ago I learned programming in APL where the "Butch" programmers did as much as possible in a single line (And in APL it's quite amazing what you can do in a single line of 15-20 characters) However it always ended up as mostly unreadable/unmaintainable. Software changes constantly and language "features" that get in the way of clarity and simnplicity should be avoided as they end up increasing costs of development and decreasing time to market. And that's what makes or breaks projects and companies. (Unless you've been through the rise and fall of a few companies that's not so obvious.) -- Steve Maillet (eMVP) Entelechy Consulting smaillet_AT_EntelechyConsulting_DOT_com/* which is more compact than.. */ x = r*cos(theta) ; y = r*sin(theta) ;
Dec 25 2003
There are two different issues being discussed in this thread, the first is multiple return values, the second is the idea of tuples. The example which you cite below is an example of the use of tuples. As such it is used to highlight the proposed syntax of tuple assignment. Furthermore, programmers can write bad code with or without tuples. The semicolon can be used to "Butch" code (as you say), e.g. x = r*cos(theta) ; y = r*sin(theta) ; There are may who have opined that the introduction of tuples would enhance the utility of the language. It is my belief that high-level languages should allow you to compactly express your *intentions* in a non-ambiguous way to the compiler. If there is a frequently encountered coding pattern which can be reduced and simplified through the introduction of a new language feature, then the benefits of such a feature should be carefully considered. It is not that tuples are in and of them selves are of that much utility that they should be added to the language, however, by introducing tuples as a language feature, multiple return values are a natural consequence. The best case which I have seen for tuples is the code to swap two variables, e.g. (x, y) = (y, x) ; /* simple, clear, concise */ other useful applications for tupples would be calculations which naturally linked as such as coordinate conversion (r, theta) = ( sqrt(x*x + y*y) , atan2(y,x) ) ; the real power of the tuple comes in multiple return values, e.g. (r, theta) = toPolar(x, y) ; ...or... (year, month, day, dayofweek) = getDate() ; ...or... (hours, min, sec) = getTime() ; Note that to get the date or time information, phobos returns a string ( toDateString() or toTimeString ) which must be parsed to retrieve the proper information. This IMO is a "poor man's" way of doing multiple returns in C. D should do better. Thank you, Mark. P.S. Merry Christmas. "Steve Maillet" <nospam1 EntelechyConsulting.com> wrote in message news:bsg80r$2s5v$1 digitaldaemon.com...or(x, y) = (r*cos(theta), r*sin(theta)) ;While it may be a few keystrokes more compact it's hardly easier to read/* which is more compact than.. */ x = r*cos(theta) ; y = r*sin(theta) ;comprehend. Many moons ago I learned programming in APL where the "Butch" programmers did as much as possible in a single line (And in APL it'squiteamazing what you can do in a single line of 15-20 characters) However it always ended up as mostly unreadable/unmaintainable. Software changes constantly and language "features" that get in the way of clarity and simnplicity should be avoided as they end up increasing costs ofdevelopmentand decreasing time to market. And that's what makes or breaks projectsandcompanies. (Unless you've been through the rise and fall of a fewcompaniesthat's not so obvious.) -- Steve Maillet (eMVP) Entelechy Consulting smaillet_AT_EntelechyConsulting_DOT_com
Dec 25 2003
"(x, y) = (y, x) ; /* simple, clear, concise */" That is NOT simple, clear nor concise. But then again neither is the traditional 3 assignments with a temp variable. In languages with templates a template library can help with a swap template. However, a built in swap/exchange statement/operator of some sort as part of the language proper is a far better answer to a common pattern such as this. -- Steve Maillet (eMVP) Entelechy Consulting smaillet_AT_EntelechyConsulting_DOT_com
Dec 30 2003
"Steve Maillet" <nospam1 EntelechyConsulting.com> wrote in message news:bst0ks$1m14$1 digitaldaemon.com..."(x, y) = (y, x) ; /* simple, clear, concise */" That is NOT simple, clear nor concise. But then again neither is the traditional 3 assignments with a temp variable. In languages withtemplatesa template library can help with a swap template. However, a built in swap/exchange statement/operator of some sort as part of the languageproperis a far better answer to a common pattern such as this.I only half-heartedly agree with your analysis, but I do agree that an inbuilt swap would be a very good thing. I'd even go so far as to suggest we have an operator for the purpose. Walter, shoot me down with your compiler-waltering lore, but how about x <> y or x >< y or x >=< y ? :) Dr Proctor
Dec 30 2003
"Charles Sanders" <sanders-consulting comcast.net> wrote in message news:bq8vs3$qos$1 digitaldaemon.com...languageBoost has accomplished these 'tuples' through some template magic, perhaps the same can be done with D, although i agree I would LOVE to see a1) Multiple return values (like Matlab)that implemented this.I'd rather see it in the language, but if it's not I've no doubt it'll find its way in when the templates get a serious shake.
Nov 28 2003
Matthew Wilson wrote:I'd rather see it in the language, but if it's not I've no doubt it'll find its way in when the templates get a serious shake.With explicit intantiation we're probably back at custom return structs... So better allow for simple type inference (Sather's ::= operator) and anonymous structs. Call them tuples then if you like. -eye
Nov 29 2003
Just a thought: I work in Matlab so I use the multiple return parameters. However, there are a few issues: -concerning the "C"/"D" return values (i.e. using "return x;" would have to be chnaged too, to accept multiple parameters). else, using a more "Pascal"-like approach, i.e. returning the output parameters with the last value they have before quiting the fcn. will simply change some fondamental concepts. -in Matlab, one feature missing is the non-reference parameters transfer. This means that, for each function affecting x you must write x=domsmthngto(x). IMO, this should be avoided in "D". Is not very cool. Felix In article <bq9e98$1f9f$1 digitaldaemon.com>, Matthew Wilson says..."Charles Sanders" <sanders-consulting comcast.net> wrote in message news:bq8vs3$qos$1 digitaldaemon.com...languageBoost has accomplished these 'tuples' through some template magic, perhaps the same can be done with D, although i agree I would LOVE to see a1) Multiple return values (like Matlab)that implemented this.I'd rather see it in the language, but if it's not I've no doubt it'll find its way in when the templates get a serious shake.
Dec 01 2003
The syntax should be: (int, float, double) funct( char[] foo, int bar) { int result1 ; float result2; double result3 ; /* do stuff */ return (result1, result2, result3) ; } This would ofcourse impose a special meaning on the parenthesis and comma for the return statement. I assume that D did away with the C-"comma operator" so there would be no ambiguity in the syntax. This amounts to nothing more than a compiler generated struct used only for the passing of parameters on return. mark. "Felix" <Felix_member pathlink.com> wrote in message news:bqesvv$310k$1 digitaldaemon.com...Just a thought: I work in Matlab so I use the multiple return parameters. However, there are a few issues: -concerning the "C"/"D" return values (i.e. using "return x;" would haveto bechnaged too, to accept multiple parameters). else, using a more"Pascal"-likeapproach, i.e. returning the output parameters with the last value theyhavebefore quiting the fcn. will simply change some fondamental concepts. -in Matlab, one feature missing is the non-reference parameters transfer.Thismeans that, for each function affecting x you must write x=domsmthngto(x).IMO,this should be avoided in "D". Is not very cool. Felix In article <bq9e98$1f9f$1 digitaldaemon.com>, Matthew Wilson says...perhaps"Charles Sanders" <sanders-consulting comcast.net> wrote in message news:bq8vs3$qos$1 digitaldaemon.com...Boost has accomplished these 'tuples' through some template magic,1) Multiple return values (like Matlab)findthe same can be done with D, although i agree I would LOVE to see alanguagethat implemented this.I'd rather see it in the language, but if it's not I've no doubt it'llits way in when the templates get a serious shake.
Dec 01 2003
In article <bqffkg$qin$1 digitaldaemon.com>, Mark J. Brudnak says...The syntax should be: (int, float, double) funct( char[] foo, int bar) { int result1 ; float result2; double result3 ; /* do stuff */ return (result1, result2, result3) ; } This would ofcourse impose a special meaning on the parenthesis and comma for the return statement. I assume that D did away with the C-"comma operator" so there would be no ambiguity in the syntax. This amounts to nothing more than a compiler generated struct used only for the passing of parameters on return. mark. "Felix" <Felix_member pathlink.com> wrote in message news:bqesvv$310k$1 digitaldaemon.com...You can already do this. You can return a struct I in C and C++. A struct can contain more than one value and encapsulate more than one return of types. It is better to return a struct of values than have a multiple return for functions. This is how it was intended to return multiple types. A link for gcc is: http://gcc.gnu.org/ml/gcc/1998-11/msg01087.html Here's an example from that link of returning a struct: ================================================================== -- z1.c -------------------------------------------------------- struct s { int x; }; struct s func (int y) { struct s xx; xx.x = y * 10; return xx; } -- z2.c -------------------------------------------------------- struct s { int x; }; extern struct s func (int y); void func2 (struct s x1, struct s x2) { printf ("%d %d\n", x1.x, x2.x); } int main () { func2 (func (1), func (2)); } ---------------------------------------------------------------- On linux, compile z1.c with gcc 2.7.2 and z2.c with egcs and link them together. The resulting program prints 10 1 rather than the expected 10 20 ==========================================================Just a thought: I work in Matlab so I use the multiple return parameters. However, there are a few issues: -concerning the "C"/"D" return values (i.e. using "return x;" would haveto bechnaged too, to accept multiple parameters). else, using a more"Pascal"-likeapproach, i.e. returning the output parameters with the last value theyhavebefore quiting the fcn. will simply change some fondamental concepts. -in Matlab, one feature missing is the non-reference parameters transfer.Thismeans that, for each function affecting x you must write x=domsmthngto(x).IMO,this should be avoided in "D". Is not very cool. Felix In article <bq9e98$1f9f$1 digitaldaemon.com>, Matthew Wilson says...perhaps"Charles Sanders" <sanders-consulting comcast.net> wrote in message news:bq8vs3$qos$1 digitaldaemon.com...Boost has accomplished these 'tuples' through some template magic,1) Multiple return values (like Matlab)findthe same can be done with D, although i agree I would LOVE to see alanguagethat implemented this.I'd rather see it in the language, but if it's not I've no doubt it'llits way in when the templates get a serious shake.
Dec 01 2003
"Makaan Kublai Kahn" <Makaan_member pathlink.com> wroteYou can already do this. You can return a struct I in C and C++. A struct can contain more than one value and encapsulate more than onereturnof types. It is better to return a struct of values than have a multiplereturnfor functions. This is how it was intended to return multiple types.Yes, but why should you have to define a structure just because you have to return two or three values rather than one? It is more code to write. The compiler knows all of the relevent information to define the structure implicitly. In other words the compiler is responsible for generating the struct. For example. FOR THE CALLER SIDE =================== D code as written: int x ; float y ; (x, y) = func(10, 3.14159, "foo") ; The compiler then compiles it as if I had written: int x ; float y ; { /* compiler generated block statement */ struct tempStruct { int var1 ; float var2 ; } tempStruct temp ; temp = func(10, 3.14159, "foo") ; x = temp.var1 ; y = temp.var2 ; } FOR THE CALLEE SIDE =================== D code as written: (int , float) = func(int a, float b, char [] c) { int result1 ; float result2 ; /* do stuff */ return( result1, result2 ) ; } The compiler then compiles it as if I had written: (int , float) = func(int a, float b, char [] c) { int result1 ; float result2 ; /* do stuff */ { /* compiler generated block statement */ struct tempStruct { int var1 ; float var2 ; } tempStruct temp ; temp.var1 = result1 ; temp.var2 = result2 ; return temp ; }/* end compiler generated block statement */ } This is also what happens to the aruments as well. They are stuffed into an implicitly defined structure consisting of either the registers and/or the stack in a well defined way. It is only natural to do the same thing in reverse. (i.e. use the registers and stack to pass back multiple return values in a well defined way. In this case our ficticious compiler used a struct, in an actual implementation it would use some registers and then the stack.) mark.A link for gcc is: http://gcc.gnu.org/ml/gcc/1998-11/msg01087.html Here's an example from that link of returning a struct: ================================================================== -- z1.c -------------------------------------------------------- struct s { int x; }; struct s func (int y) { struct s xx; xx.x = y * 10; return xx; } -- z2.c -------------------------------------------------------- struct s { int x; }; extern struct s func (int y); void func2 (struct s x1, struct s x2) { printf ("%d %d\n", x1.x, x2.x); } int main () { func2 (func (1), func (2)); } ---------------------------------------------------------------- On linux, compile z1.c with gcc 2.7.2 and z2.c with egcs and link them together. The resulting program prints 10 1 rather than the expected 10 20 ==========================================================
Dec 01 2003
In article <bqgbtf$2726$1 digitaldaemon.com>, Mark J. Brudnak says..."Makaan Kublai Kahn" <Makaan_member pathlink.com> wroteFunctions returning several values could be used like (a,b,c) = func(d,e,f,g); Using this we could make the code clearer and easier to understand if we decided that (d,e,f,g) could only be in-parameters, and that the only way to get out- functionality is via return values (e.g. (a,b,c)). This would make the code quite readable. But the cost, and the pre-requisite, would be to skip out-parameters entirely from the language. Why? Well, if we are browsing code written by others, then we either can rely on the right side being input- only, or then we can't. Only if we can do that, the code becomes readily browsable for us. This brings up the question, should we do this? I for one would think that this is a truly interesting aspect, and it may contain quite some promises. OTOH, this would be such a profound change in the language that we may risk alienating C(++), Java, and other users. So, this had better be worth the cost. Also, if we went for this kind of strategy, then why not make both the in- (the right side) and the out- (the left side) streamable! That is, a function could take any number of parameters, and it could also return an arbitrary number of parameters! Well, such languages exist already. APL I think is one. But from what I've had to program with APL, this sure doesn't contribute to the overall readability when it comes right down to it. Then there is another solution. A company using D could internally decide that every function takes one in-parameter and one out-parameter. They would be structs. This would of course lead to assignments both at the input and the output, but since Good Code has short functions, most of the locals could be in structs to begin with. Standardising these structs could result in increased clarity and maybe even more overall structure in the program. And we could skip a profound remake of D.You can already do this. You can return a struct I in C and C++. A struct can contain more than one value and encapsulate more than one return of types. It is better to return a struct of values than have a multiple return for functions. This is how it was intended to return multiple types.
Dec 01 2003
Also, if we went for this kind of strategy, then why not make both the in- (the right side) and the out- (the left side) streamable! That is, a function could take any number of parameters, and it could also return an arbitrary number of parameters! Well, such languages exist already. APL I think is one. But from what I've had to program with APL, this sure doesn't contribute to the overall readability when it comes right down to it.MATLAB allows both a variable number of inputs and outputs. It does this by reserving the parameter names "varargin" and "varargout" to have special meaning (they collect all the remaining inputs or outputs into a list). It also defines the variables "nargin" and "nargout" in the function body to be the number of inputs and outputs. Multiple outputs are used very often in MATLAB code. varargout is used much less frequently, and most uses probably are to implement generic function evaluators. -Ben
Dec 01 2003
"Ben Hinkle" <bhinkle4 juno.com> wroteMATLAB allows both a variable number of inputs and outputs. It does thisbyreserving the parameter names "varargin" and "varargout" to have special meaning (they collect all the remaining inputs or outputs into a list). It also defines the variables "nargin" and "nargout" in the function body tobethe number of inputs and outputs. Multiple outputs are used very often in MATLAB code. varargout is usedmuchless frequently, and most uses probably are to implement generic function evaluators. -BenYes, but Matlab != D Matlab is interpreted and is therefore slow. Don't get me wrong, I love Matlab, but when speed is necessary, a compiled, optimized language is necesary. For me, I like C, I avoid C++ and D is appealing. Since D is still being developed, multiple returns seem like a nice addition. Mark.
Dec 01 2003
How would multiple returns work if you don't provide places for the returns to go? ie (int, int) = someFunc(int); (a) = someFunc(10); Further to that, how would nested functions work? (int) = someFunc(int, int, int) (int, int, int) = foo(float) (a) = someFunc(foo(10.0)); What about determining which function to call based on the return type? (int) = foo(int) (int, int) = foo(int) (a,b) = foo(10); c = foo(5); I don't know how complex that is starting to get for the compiler. I like the idea of mulitple returns, it can be very handy - but I get the feeling that it is probably quite hard to implement in a compiler. Brad"Ben Hinkle" <bhinkle4 juno.com> wroteMATLAB allows both a variable number of inputs and outputs. It does thisbyreserving the parameter names "varargin" and "varargout" to have special meaning (they collect all the remaining inputs or outputs into a list). It also defines the variables "nargin" and "nargout" in the function body tobethe number of inputs and outputs. Multiple outputs are used very often in MATLAB code. varargout is usedmuchless frequently, and most uses probably are to implement generic function evaluators. -BenYes, but Matlab != D Matlab is interpreted and is therefore slow. Don't get me wrong, I love Matlab, but when speed is necessary, a compiled, optimized language is necesary. For me, I like C, I avoid C++ and D is appealing. Since D is still being developed, multiple returns seem like a nice addition. Mark.
Dec 01 2003
"brad beveridge" <brad nospam.com> wrote in message news:bqguk7$31jb$1 digitaldaemon.com...How would multiple returns work if you don't provide places for the returns to go? ie (int, int) = someFunc(int);A call would look like this. type1 foo ; type2 bar ; (foo, bar) = someFunc(param1, param2, /* etc*/) ;(a) = someFunc(10); Further to that, how would nested functions work? (int) = someFunc(int, int, int) (int, int, int) = foo(float) (a) = someFunc(foo(10.0));Nesting for the time being should not be allowed. The function should return a parameterized rvalue ready for assignment to a suitable lvalue. If a compelling case arises this could be explored.What about determining which function to call based on the return type? (int) = foo(int) (int, int) = foo(int) (a,b) = foo(10); c = foo(5);Probably not a good place to start.I don't know how complex that is starting to get for the compiler. I like the idea of mulitple returns, it can be very handy - but I get the feeling that it is probably quite hard to implement in a compiler. BradIt"Ben Hinkle" <bhinkle4 juno.com> wroteMATLAB allows both a variable number of inputs and outputs. It does thisbyreserving the parameter names "varargin" and "varargout" to have special meaning (they collect all the remaining inputs or outputs into a list).toalso defines the variables "nargin" and "nargout" in the function bodyfunctionbethe number of inputs and outputs. Multiple outputs are used very often in MATLAB code. varargout is usedmuchless frequently, and most uses probably are to implement genericevaluators. -BenYes, but Matlab != D Matlab is interpreted and is therefore slow. Don't get me wrong, I love Matlab, but when speed is necessary, a compiled, optimized language is necesary. For me, I like C, I avoid C++ and D is appealing. Since D is still being developed, multiple returns seem like a nice addition. Mark.
Dec 01 2003
Hello Brad,How would multiple returns work if you don't provide places for the returns to go? ie (int, int) = someFunc(int); (a) = someFunc(10);Two possibilities: 1) Compiler error - all parameters are mandatory 2) When there are fewer LHS variables, they are assigned starting from the first one, if types match. Harder for everyone, though.Further to that, how would nested functions work? (int) = someFunc(int, int, int) (int, int, int) = foo(float) (a) = someFunc(foo(10.0));One useful feature of tuples in Python is automatic packing and unpacking. (int, float) Func(); // Or just "int, float Func()"? and call it as: int i; float f; i, f = Func(); With the compiler automatically managing the packing into a tuple. Your "nested functions" (I would think they are an entirely different beast!) could benefit from automatic unpacking as well. (a) = someFunc(foo(10.0)); This would translate into a = someFunc(a, b, c); where a,b,c forms the tuple (a, b, c) returned by foo().What about determining which function to call based on the return type? (int) = foo(int) (int, int) = foo(int) (a,b) = foo(10); c = foo(5);In this case there is no ambiguity. In fact, these are unrelated issues - returning multiple values and overloading on return types. Actually if you have the former, there is less incentive to have the latter. The whole issue of overloading by return type is probably centered around the fact that in most languages one can ignore the return type. I am told Ada supports overloading on return types and return values can never be ignored. Anyone with good Ada experience would like to comment?I don't know how complex that is starting to get for the compiler. I like the idea of mulitple returns, it can be very handy - but I get the feeling that it is probably quite hard to implement in a compiler.I remember seeing a discussion on the web (couple of years back?) by the designers of C, C++ and Java. Asked what they would change if they were to do it all over again, James Gosling cited multiple return values as a major one (Ha, I found an archived link - http://www.gotw.ca/publications/c_family_interview.htm). Of course, I am not advocating anything here. Multiple return values is one feature, I think, that can't be added as an afterthought. I mean, in a seamless manner. I think that may be the reason Java still doesn't have it. All of the things discussed in this thread exist in various other languages. But of course, that's not enough of a reason to put them all into D. Cheers, Sarat Venugopal
Dec 02 2003
What's good for MATLAB is not necessarily good for D. These are two VERY different languages with different problem domains, and users. I've lived through some REALLY long debug sessions where someone used a language feature to save a couple of bytes of source code space instead of making it clear and simple to understand. A struct or class makes more sense as the returned values are all related together in some way or they wouldn't be returned from the same function. -- Steve Maillet (eMVP) Entelechy Consulting smaillet_AT_EntelechyConsulting_DOT_com
Dec 25 2003
"Steve Maillet" <nospam1 EntelechyConsulting.com> wrote in message news:bsg8f3$2t06$1 digitaldaemon.com...What's good for MATLAB is not necessarily good for D. These are two VERY different languages with different problem domains, and users.Agreed!I've lived through some REALLY long debug sessions where someone used a language feature to save a couple of bytes of source code space instead of makingitclear and simple to understand.Some language features can be used with great power by some and abused to great extremes by others. This says more about the programmer than it does about the feature. (it is unfortunate that there are many books which encourage the abuse of language features, especially C books.)A struct or class makes more sense as the returned values are all related together in some way or they wouldn't be returned from the same function.Not true. If a structure's only purpose is to return multiple values, then IMO it complicates an interface rather than simplifies it because a temporary instance must be created to shuffle out of the function.-- Steve Maillet (eMVP) Entelechy Consulting smaillet_AT_EntelechyConsulting_DOT_comFinally, I think that the reason that functions only return one value has more to do with mathematics than with computer science. The name is borrowed from the familiar mathematical concept we all learned in Algebra, Trig, Calc, for example, log(x), tan(y), sin(z), etc. The reality is that most of the mathematical functions which are handled in these courses are "single valued" meaning that they map to the real numbers. Occasionally we studied functions which take complex values. Similarly on the parameter side, we often encounter single parameters in our math classes. For some reason, when the computer scientists borrowed the concept, they extended and generalized the parameters to be multiple valued, but, in general, did not extend the return values in the same way. The reason for this IMO (this is pure speculation) is that in math class we were all taught that "functions are single valued" meaning that each point in the domain must map to *only one* point in the range. Mathematical functions, however, are defined as a mapping from the domain to the range where each element in the range may very well be an aggregate of simpler objects, or multiple valued. Having said this, I think multiple return vales would be logical generalization of the borrowed concept of a function just as multiple parameters were. Mark.
Dec 25 2003
A struct or class makes more sense as the returned values are all related together in some way or they wouldn't be returned from the same function.so all of your functions only have one parameter as well? because this makes more sence then as well. and if multiple parameters are needed, you pass them as struct, right?
Dec 26 2003
You are comparing apples to oranges the mathematical definition of a function allows for multiple inputs and a single output. (Note: that output can be a complex number, a vector or matrix, etc...) The idea of multiple return types goes against that. It also makes for some very ugly and difficult to debug code. I've been there and done that and most of the time there is no need for it and the few times that it is required struts work just fine and are easy enough to code. Should the language have a means to automatically and efficiently handle the return of a strict so there isn't a copy involve - sure. But that's a compiler implementation detail not a language definition one. -- Steve Maillet (eMVP) Entelechy Consulting smaillet_AT_EntelechyConsulting_DOT_com
Dec 30 2003
In article <bst09c$1le5$1 digitaldaemon.com>, Steve Maillet says...You are comparing apples to oranges the mathematical definition of a function allows for multiple inputs and a single output. (Note: that output can be a complex number, a vector or matrix, etc...) The idea of multiple return types goes against that. It also makes for some very ugly and difficult to debug code.Why would x, y = func(a, b) be any harder to debug than func(a, b, &x, &y) ??? To me, the 1st form is better because you see what are the inputs and outputs. In the second form, you could be passing pointers for efficiency, to for "out" parameters. Worse, in C++, the 2nd form could be: func(a, b, x, y) // declaration: void func(T a, T b, T& x, T& y) It's much harder to tell what are the inputs and what are the outputs... You could think of multiple return as returning a composite object (tuple) and decomposing it at the assignment. So, it doesn't go against your beloved math. (i don't think programming is math, but...)
Dec 30 2003
It wouldn't - both versions of the syntax, quite frankly, suck. instead it should be: Point pos = func(a,b); or perhaps Point input; Point Output; Output = func(Input); depending on exactly what it is that func is doing. -- Steve Maillet (eMVP) Entelechy Consulting smaillet_AT_EntelechyConsulting_DOT_comWhy would x, y = func(a, b) be any harder to debug than func(a, b, &x, &y)
Dec 31 2003
Steve Maillet wrote:that would be very nice, as thats whats im used to also. You should definetly be able to return a struct (if you cant) and a value from an non-anonymous enum, and a object. in vb we can do something like this Listview lv = new Listview; //this dynamicly adds an item, returns a reference and you can inline add text to the subitem lv.ListItems.Add("test","test").SubItems(1).Text = "test"; //or struct Foo { int A; int B; } Foo InitStruct(int a,int b) { Foo c; c.A = a; c.B = b; return c; } //which i think you can already do, but even better would be Foo InitStruct(int a,int b) { InitStruct.A = a; InitStruct.B = b; return; }It wouldn't - both versions of the syntax, quite frankly, suck. instead it should be: Point pos = func(a,b); or perhaps Point input; Point Output; Output = func(Input); depending on exactly what it is that func is doing.Why would x, y = func(a, b) be any harder to debug than func(a, b, &x, &y)
Dec 31 2003
"You could think of multiple return as returning a composite object (tuple)" Yes, you could and IMHO you SHOULD. The beauty of that is that __EXISTING__ language constructs allow you to do so already! Templates/generics allow you to create typesafe Tuple templates for any kind of paired return type; in fact STL already has the Pair template for C++ programmers to do just that. This is far more flexible and allows for compile time type checking without inventing or adding new concepts into the language. As I, and others, have mentioned the syntax of returning a struct or class is a bit clumsy in most "C" derivative languages and there is room to improve that in a new and emerging language such as "D". However, adding a completely new concept that is adequately supported with other existing constructs is a bad idea. (Especially when the only reason for not using a struct/class as a return type that has been offered thus far is the "clumsy" syntax of creating a temp in the actual method implementation. [Remember that even in the beloved multiple return values the compiler will have to do that underneath anyway.) So, I say lets' focus on ideas to improve that syntax without breaking the familiarity with C or compromising efficiency. By way of some examples VB and Pascal use the function name as an implicit local for the return value so we could make a function like this: Point Foo(float r, float theta) { Foo.x = r*cos(theta) ; Foo.y = r*sin(theta) ; } The compiler is able to optimize that to the actual return type and eliminate any copy on return in many cases. However, the existing return statement should be supported as well. This resolves the syntactical issues and provides for highly flexible tuples and other multiple return types using __EXISTING__ typesafe language constructs with minimal effort on the compiler creators and no further imposition on the programmer. Furthermore, using the above syntax and structs allows for assignment of the members in any particular order without the need to create or store temps. Consider how the code would have to look if the resulting return type were implemented as proposed (e.g. "(x, y) = (r*cos(theta), r*sin(theta)) ") The language would HAVE to specifiy an order of execution for the sub expressions of the rvalue. And in the case where the actual functions needed to operate in a different order things get ugly with temps really fast. However, using structures or objects (with a minor syntactical cleanup) as shown above the issue simply doesn't exist. -- Steve Maillet (eMVP) Entelechy Consulting smaillet_AT_EntelechyConsulting_DOT_com
Dec 31 2003
Steve Maillet wrote:fact STL already has the Pair template for C++ programmers to do just that.Yup. and there are tuples in boost. The problem is, D templates lack of implicit instantiation, which makes them much less appropriate for this kind of stuff. However, Walter promised some changes in templates. I wonder what those would be. I would prefer for templates to stay as they are, bacause they are great for many things and are nontheless simple to implement correctly. Also, they already open up another world on efficiency. In C++, templates are used to patch up the otherwise minimalistic language. That was not the original idea of D. That's why we have sliced and associative arrays directly in the langiage. And thus i would prefer that tuples (anonymous structs) also make it into the language. -eye
Jan 01 2004
"Steve Maillet" <nospam1 EntelechyConsulting.com> wrote in message news:bsurmr$19dt$1 digitaldaemon.com..."You could think of multiple return as returning a composite object(tuple)"Yes, you could and IMHO you SHOULD. The beauty of that is that__EXISTING__language constructs allow you to do so already! Templates/generics allowyouto create typesafe Tuple templates for any kind of paired return type; in fact STL already has the Pair template for C++ programmers to do justthat. Defining a struct for the sole purpose of returning multiple values is the simplest way, defining a template to do this is just down right cumbersome and unnecessary.This is far more flexible and allows for compile time type checkingwithoutinventing or adding new concepts into the language.Tuples can be compile time checked, but at the element level. In the truest sense there is no type associated with a tuple. It is a collection of types which is implicitly defined by the types it contains. These types must match across an assignment.As I, and others, have mentioned the syntax of returning a struct or class is a bit clumsy inmost"C" derivative languages and there is room to improve that in a new and emerging language such as "D". However, adding a completely new conceptthatis adequately supported with other existing constructs is a bad idea.Multiple returns and tuples are not new concepts. Taking your point to the extremes, most of the features of D are not necessary. They are there because they make frequently encountered patterns easier. Why was array slicing introduced in D? Because it makes frequent tasks easier to code. They do not add new ability to manipulate arrays, they just make it easier.(Especially when the only reason for not using a struct/class as a return type that has been offered thus far is the "clumsy" syntax of creating a temp in the actual method implementation. [Remember that even in thebelovedmultiple return values the compiler will have to do that underneathanyway.) IMO the more the compiler does "underneath" the better. That is the point of high-level programming languages.So, I say lets' focus on ideas to improve that syntax without breaking the familiarity with C or compromising efficiency.D has broken with C/C++ in several areas, introducing new constructs where needed. C is 30+ years old, C++ is 20+ years old. New ideas have been introduced in newer languages. I would be foolish to reject new constructs just to stay with C/C++ syntax.By way of some examples VB and Pascal use the function name as an implicit local for the return value so we could make a function like this: Point Foo(float r, float theta) { Foo.x = r*cos(theta) ; Foo.y = r*sin(theta) ; } The compiler is able to optimize that to the actual return type and eliminate any copy on return in many cases. However, the existing return statement should be supported as well. This resolves the syntacticalissuesand provides for highly flexible tuples and other multiple return types using __EXISTING__ typesafe language constructs with minimal effort on the compiler creators and no further imposition on the programmer. Furthermore, using the above syntax and structs allows for assignment ofthemembers in any particular order without the need to create or store temps. Consider how the code would have to look if the resulting return type were implemented as proposed (e.g. "(x, y) = (r*cos(theta), r*sin(theta)) ")OK. --- callee side --- (float, float) Foo(float r, float theta) { return ( r*cos(theta), r*sin(theta) ) ; } --- caller side --- (x, y) = Foo(r, theta) ;The language would HAVE to specifiy an order of execution for the sub expressions of the rvalue.The D spec says that the order of execution within a statement is reserved for the compiler to determine. Tuples would be the same way.And in the case where the actual functions needed to operate in a different order things get ugly with temps really fast. However, using structures or objects (with a minor syntactical cleanup) as shown above the issue simply doesn't exist.In your way of thinking, you should always use a temporary structure to pass multiple parameters as well. What is the difference between a = func(b, c, d) ; ...and ... (e, f, g) = func(h) ; In your argument both cases are unnecessary and should be coded as. struct Foo { type1 a ; type2 b ; type3 c ; } Foo foo ; foo.a = 1 ; foo.b = 2 ; foo.c = 3 ; a = func(foo) ; ...and ... struct Foo { type1 e ; type2 f ; type3 g ; } Foo foo = func(h) ; ; type1 e = foo.e ; type2 f = foo.f ; type3 g = foo.g ; I do not see the efficiency in this. Mark.-- Steve Maillet (eMVP) Entelechy Consulting smaillet_AT_EntelechyConsulting_DOT_com
Jan 01 2004
We should crawl before we walk or run. I think a nice start would be to implement multiple return values. (a, b, c) = foo(p1, p2, p3) ; 1) Rules for passing parameters remain the same. 2) Functions may not be over loaded via their return parameter lists. 3) Define parameterized lvalues and rvalues. i.e. (a, b, c) = (e+f, z*u, n*m) ; /* valid statement */ i.e. (x, y) = (r*cos(theta), r*sin(theta)) ; /* valid statement */ i.e. (x, y) = toCartesian( r, theta) ; /* toCartesian returns a parmeterized rvalue */ 4) Multiple return values are passed back via registers and stack in a well-defined way. 5) Single output functions use the current calling conventions. 6) Multiple return value functions cannot be linked by another language. The call is D to D. Mark. "Georg Wrede" <Georg_member pathlink.com> wroteFunctions returning several values could be used like (a,b,c) = func(d,e,f,g); Using this we could make the code clearer and easier to understand if we decided that (d,e,f,g) could only be in-parameters, and that the only way to get out- functionality is via return values (e.g. (a,b,c)).Nice, but not necessary.This would make the code quite readable. But the cost, and the pre-requisite, would be to skip out-parameters entirely from the language.Not necessary. This would certainly break existing code and also break C backward compatability (I think).Why? Well, if we are browsing code written by others, then we either can rely on the right side being input- only, or then we can't. Only if we can do that, the code becomes readily browsable for us. This brings up the question, should we do this? I for one would think that this is a truly interesting aspect, and it may contain quite some promises. OTOH, this would be such a profound change in the language that we may risk alienating C(++), Java, and other users. So, this had better be worth the cost.I do not think this would be a profound change.Also, if we went for this kind of strategy, then why not make both the in- (the right side) and the out- (the left side) streamable! That is, a function could take any number of parameters, and it could also return an arbitrary number of parameters! Well, such languages exist already. APL I think is one. But from what I've had to program with APL, this sure doesn't contribute to the overall readability when it comes right down to it.This would a lot all at once.Then there is another solution. A company using D could internally decide that every function takes one in-parameter and one out-parameter. They would be structs. This would of course lead to assignments both at the input and the output, but since Good Code has short functions, most of the locals could be in structs to begin with. Standardising these structs could result in increased clarity and maybe even more overall structure in the program. And we could skip a profound remake of D.
Dec 01 2003
In article <bqgvbc$14a$1 digitaldaemon.com>, Mark Brudnak wrote:We should crawl before we walk or run. I think a nice start would be to implement multiple return values. (a, b, c) = foo(p1, p2, p3) ; 1) Rules for passing parameters remain the same. 3) Define parameterized lvalues and rvalues. i.e. (a, b, c) = (e+f, z*u, n*m) ; /* valid statement */ i.e. (x, y) = (r*cos(theta), r*sin(theta)) ; /* valid statement */ i.e. (x, y) = toCartesian( r, theta) ; /* toCartesian returns a parmeterized rvalue */I must ask, how would a statement like the second one be implemented? Maybe like this: x = r*cos(theta); y = r*sin(theta); Or perhaps like this: __temp1 = r*cos(theta); __temp2 = r*sin(theta); x = __temp1; y = __temp2; The latter would be less straightforward but would save the user from the bug of trying to swap variables with "(x, y) = (y, x);"4) Multiple return values are passed back via registers and stack in a well-defined way.The same way that structs are returned, I presume. Another question: could the grammar be changed so that tuples would not need the enclosing ()'s, just like in someone's python example? Which is more readable, more maintainable, more comfortable? Alternative 1: int x; int y; (int, int) f(int, int); (x, y) = f(1, 2); Alternative 2: int x; int y; int, int f(int, int); x, y = f(1, 2); Yet another question: Is the following possible? int x, y; and what does it mean? Does it declare two integers, or is it half tuple, half declaration? Should I be able to write this: int x; x, int y = f(1, 2); // or maybe: (x, int y) = f(1, 2); Does this complicate parsing?You most certainly do not mean this but something else, because the C language does not have out parameters. It would break compatibility, at least in spirit, with languages and conventions which use "in" and "out" declarations; IDL comes to mind. Finally, I agree that both multiple return values and tuples should be part of any modern programming language, and that they are much cleaner alternative than "out parameters" which is a contradiction in terms (not to mention that one man's in is another man's out). But it is also true that they don't come for free. First, the sequencing operator must be ditched and a proper workaround found. Then, the grammar must be revised to see whether the language can consume such a pervasive change (as the comma is used everywhere in language where lists exist, I expect that there may rise conflicts between the customary usages and tuple usage). Finally, the semantics of the tuples must be worked out with the proper care and attention so that will fit in the language as if originally designed for it, that they won't create any pitfalls, and that they won't break (too many) existing idioms. -AnttiThis would make the code quite readable. But the cost, and the pre-requisite, would be to skip out-parameters entirely from the language.Not necessary. This would certainly break existing code and also break C backward compatability (I think).
Dec 03 2003
"Antti Sykäri" <jsykari gamma.hut.fi> wrote <snip>I must ask, how would a statement like the second one be implemented? Maybe like this: x = r*cos(theta); y = r*sin(theta); Or perhaps like this: __temp1 = r*cos(theta); __temp2 = r*sin(theta); x = __temp1; y = __temp2; The latter would be less straightforward but would save the user from the bug of trying to swap variables with "(x, y) = (y, x);"This would be legal, because the tuple-operator (,,,,,) would have *higher* precidence than the assignment operator. More importantly, each item in the RHS tuple would be evaluated. i.e. (re, im) = (exp(re)*cos(im), exp(re)*sin(im)) ; /* complex exponentiation */ Here exp(re) would be evaluated twice.Yes, exactly.4) Multiple return values are passed back via registers and stack in a well-defined way.The same way that structs are returned, I presume.Another question: could the grammar be changed so that tuples would not need the enclosing ()'s, just like in someone's python example? Which is more readable, more maintainable, more comfortable? Alternative 1: int x; int y; (int, int) f(int, int); (x, y) = f(1, 2);Yes, very clear.Alternative 2: int x; int y; int, int f(int, int); x, y = f(1, 2);No, it is not symmetric.Yet another question: Is the following possible? int x, y; and what does it mean? Does it declare two integers, or is it half tuple, half declaration? Should I be able to write this: int x; x, int y = f(1, 2); // or maybe:No, it is not clear you have a tuple on the LHS.(x, int y) = f(1, 2);Does D allow this in other areas? It is probably best to follow the D rules. Is it legal to write: int y = foo(1,2) ; <snip>
Dec 04 2003
With structs but you have the advantage of selecting whatever value you want from a returned struct. With multiple returns you have to consider all of the return values. There is a slight advantage to a packaged multiple return. This allows you to package a set of values for return and keep the syntax simpler. You can select out of the return bundle whatever value you want. The Java designers were very oversighted in removing structs. Without structs and without multiple returns there is no way to include or substitute multiple returns. So structs are useful without multiple return. In article <bqgbtf$2726$1 digitaldaemon.com>, Mark J. Brudnak says..."Makaan Kublai Kahn" <Makaan_member pathlink.com> wroteYou can already do this. You can return a struct I in C and C++. A struct can contain more than one value and encapsulate more than onereturnof types. It is better to return a struct of values than have a multiplereturnfor functions. This is how it was intended to return multiple types.Yes, but why should you have to define a structure just because you have to return two or three values rather than one? It is more code to write. The compiler knows all of the relevent information to define the structure implicitly. In other words the compiler is responsible for generating the struct. For example. FOR THE CALLER SIDE =================== D code as written: int x ; float y ; (x, y) = func(10, 3.14159, "foo") ; The compiler then compiles it as if I had written: int x ; float y ; { /* compiler generated block statement */ struct tempStruct { int var1 ; float var2 ; } tempStruct temp ; temp = func(10, 3.14159, "foo") ; x = temp.var1 ; y = temp.var2 ; } FOR THE CALLEE SIDE =================== D code as written: (int , float) = func(int a, float b, char [] c) { int result1 ; float result2 ; /* do stuff */ return( result1, result2 ) ; } The compiler then compiles it as if I had written: (int , float) = func(int a, float b, char [] c) { int result1 ; float result2 ; /* do stuff */ { /* compiler generated block statement */ struct tempStruct { int var1 ; float var2 ; } tempStruct temp ; temp.var1 = result1 ; temp.var2 = result2 ; return temp ; }/* end compiler generated block statement */ } This is also what happens to the aruments as well. They are stuffed into an implicitly defined structure consisting of either the registers and/or the stack in a well defined way. It is only natural to do the same thing in reverse. (i.e. use the registers and stack to pass back multiple return values in a well defined way. In this case our ficticious compiler used a struct, in an actual implementation it would use some registers and then the stack.) mark.A link for gcc is: http://gcc.gnu.org/ml/gcc/1998-11/msg01087.html Here's an example from that link of returning a struct: ================================================================== -- z1.c -------------------------------------------------------- struct s { int x; }; struct s func (int y) { struct s xx; xx.x = y * 10; return xx; } -- z2.c -------------------------------------------------------- struct s { int x; }; extern struct s func (int y); void func2 (struct s x1, struct s x2) { printf ("%d %d\n", x1.x, x2.x); } int main () { func2 (func (1), func (2)); } ---------------------------------------------------------------- On linux, compile z1.c with gcc 2.7.2 and z2.c with egcs and link them together. The resulting program prints 10 1 rather than the expected 10 20 ==========================================================
Dec 06 2003
I currently think it's a good idea to unify structs and parameter lists, and tuples are basically anonymous structs with anonymous fields (only way to get values back out is by pattern matching on types) What is a parameter list anyhow but a shape of a collection of values at some point in the flow of execution. On the way into a function is a valid point in the flow of execution. So is the return, or should be. A way to flexibly map structs to structs, or tuples to tuples, or tuples to structs, would make this sort of thing very convenient. I think D is aiming more toward status quo remaining largely C compatible. Sean "Commander Odama" <Commander_member pathlink.com> wrote in message news:bqu23r$1io7$1 digitaldaemon.com...With structs but you have the advantage of selecting whatever value youwantfrom a returned struct. With multiple returns you have to consider all of the return values. There is a slight advantage to a packaged multiple return. This allows you to package a set of values for return and keep the syntax simpler.You canselect out of the return bundle whatever value you want. The Java designers were very oversighted in removing structs. Withoutstructsand without multiple returns there is no way to include or substitutemultiplereturns. So structs are useful without multiple return.
Dec 07 2003
Sean L. Palmer wrote:I currently think it's a good idea to unify structs and parameter lists, and tuples are basically anonymous structs with anonymous fields (only way to get values back out is by pattern matching on types)This would requiere big changes in the language. Let the fields rather be named alphabetivally in their order: a,b,c,... This gives us 26 fields, which is usually quite enough - everything larger than 5 is better advised being a struct. I'm not sure Further fields are requiered, but then they could be named aa, ab, ac, ... zz. :) Also array indexing operator could be used as a notation for indexing fields by ordinal. This would in turn requiere a type inference assignment operator, which is a useful beast all by itself, and work in the cases where the current normal compiler can figure out the type of right hand side expression. instaed of : MyObjectType a = new MyObjectType(blahblah); you could write: a := new MyObjectType. for a function which returns multiple values: ret := FSinCos(); An unnamed strauct corresponding to type of ret would need to be implicitly declared just before use: struct trowaway_blahblah {real a; real b;} And the declaration of FSinCos should be: (real, real) FSinCos (real a); I believe this also reuieres that we change semantics of the comma operator, which would then return a tuple, instead of only the last value. This would nontheless allow the most common use of comma operator in C, which is to stuff up more into the for loop declaration. One possible problem is that this could make declaration of a tuple of tuples problematic...What is a parameter list anyhow but a shape of a collection of values at some point in the flow of execution. On the way into a function is a valid point in the flow of execution. So is the return, or should be.True.A way to flexibly map structs to structs, or tuples to tuples, or tuples to structs, would make this sort of thing very convenient.Sounds complicated.I think D is aiming more toward status quo remaining largely C compatible.Hm... Who needs the curent comma operator anyway? -eye
Dec 07 2003
"Ilya Minkov" <minkov cs.tum.edu> wrote in message news:bqve80$nk9$1 digitaldaemon.com...Sean L. Palmer wrote:andI currently think it's a good idea to unify structs and parameter lists,totuples are basically anonymous structs with anonymous fields (only wayAs I said, D probably won't go for it. Your idea of using a thru z for the names isn't bad at all.get values back out is by pattern matching on types)This would requiere big changes in the language. Let the fields rather be named alphabetivally in their order: a,b,c,... This gives us 26 fields, which is usually quite enough - everything larger than 5 is better advised being a struct. I'm not sure Further fields are requiered, but then they could be named aa, ab, ac, ... zz. :) Also array indexing operator could be used as a notation for indexing fields by ordinal.This would in turn requiere a type inference assignment operator, which is a useful beast all by itself, and work in the cases where the current normal compiler can figure out the type of right hand side expression. instaed of : MyObjectType a = new MyObjectType(blahblah); you could write: a := new MyObjectType. for a function which returns multiple values: ret := FSinCos(); An unnamed strauct corresponding to type of ret would need to be implicitly declared just before use: struct trowaway_blahblah {real a; real b;} And the declaration of FSinCos should be: (real, real) FSinCos (real a);But if you do give the return values names, it would be more self-documenting and robust against later changes, say adding new return values or rearranging them.I believe this also reuieres that we change semantics of the comma operator, which would then return a tuple, instead of only the last value. This would nontheless allow the most common use of comma operator in C, which is to stuff up more into the for loop declaration.I doubt that will happen. ;(toA way to flexibly map structs to structs, or tuples to tuples, or tuplesHaskell has something like this, where you can create a new data structure based on the contents of some other one, but providing overrides for some of the values. struct point { float x,y; } struct size { float width,height; } point mypoint; size distancetoorigin = mypoint { width = x, height = y }; Something like that, but the above syntax is not good.structs, would make this sort of thing very convenient.Sounds complicated.compatible.I think D is aiming more toward status quo remaining largely CHm... Who needs the curent comma operator anyway?Nobody. It has very few uses, and those are questionable: Comma Operator Use 1: putting more than one assignment into a statement controlled by an if without having to use curly braces: if (foo > bar) x = foo, y = bar; which can easily be written thusly, no big deal: if (foo > bar) { x = foo; y = bar; } Comma Operator Use 2: doing some calculation before return int fn() { int x,y; return x = get_x(), y = get_y(), x*x + y*y + 1; } It would be clearer if written like this anyway: int fn() { int x = get_x(); int y = get_y(); return x*x + y*y + 1; } Comma Operator Use 3: for loops for (int i = 0, j = 1; i < 10 && j != i; ++i, j = i*3) printf("i = %d, j = %d\n", i, j); One could argue that this for loop is trying to do too much anyway. But the language could easily be extended in a slightly different way: allow statement blocks anywhere a statement is allowed, even in the 3rd section of a for loop: for (int i = 0, j = 1; i < 10 && j != i; { ++i; j = i*3; }) printf("i = %d, j = %d\n", i, j); That's a bad example because ++i, j = i*3 could be written j = ++i*3; Anyway the point is, there is not much the comma operator can do that can't easily be expressed some other, more legible way. It would be nice to have comma operator available for something truly useful, like tuples. Sean
Dec 07 2003
"Sean L. Palmer" <palmer.sean verizon.net> wrote in message news:br036k$1lis$1 digitaldaemon.com...Anyway the point is, there is not much the comma operator can do thatcan'teasily be expressed some other, more legible way. It would be nice tohavecomma operator available for something truly useful, like tuples. SeanIndeed... I've only used the comma operator in for loops, and that was only in a dubious effort to save space. Tuples would be a much better use of the syntax, IMHO. Dan
Dec 08 2003
In article <br036k$1lis$1 digitaldaemon.com>, Sean L. Palmer says..."Ilya Minkov" <minkov cs.tum.edu> wrote in message news:bqve80$nk9$1 digitaldaemon.com...Also note that if tuples are entities on their own, then they can be both L-values and R-values of an assignment. So you could write. if (foo > bar) (x,y) = (foo,bar) ;Sean L. Palmer wrote:andI currently think it's a good idea to unify structs and parameter lists,totuples are basically anonymous structs with anonymous fields (only wayAs I said, D probably won't go for it. Your idea of using a thru z for the names isn't bad at all.get values back out is by pattern matching on types)This would requiere big changes in the language. Let the fields rather be named alphabetivally in their order: a,b,c,... This gives us 26 fields, which is usually quite enough - everything larger than 5 is better advised being a struct. I'm not sure Further fields are requiered, but then they could be named aa, ab, ac, ... zz. :) Also array indexing operator could be used as a notation for indexing fields by ordinal.This would in turn requiere a type inference assignment operator, which is a useful beast all by itself, and work in the cases where the current normal compiler can figure out the type of right hand side expression. instaed of : MyObjectType a = new MyObjectType(blahblah); you could write: a := new MyObjectType. for a function which returns multiple values: ret := FSinCos(); An unnamed strauct corresponding to type of ret would need to be implicitly declared just before use: struct trowaway_blahblah {real a; real b;} And the declaration of FSinCos should be: (real, real) FSinCos (real a);But if you do give the return values names, it would be more self-documenting and robust against later changes, say adding new return values or rearranging them.I believe this also reuieres that we change semantics of the comma operator, which would then return a tuple, instead of only the last value. This would nontheless allow the most common use of comma operator in C, which is to stuff up more into the for loop declaration.I doubt that will happen. ;(toA way to flexibly map structs to structs, or tuples to tuples, or tuplesHaskell has something like this, where you can create a new data structure based on the contents of some other one, but providing overrides for some of the values. struct point { float x,y; } struct size { float width,height; } point mypoint; size distancetoorigin = mypoint { width = x, height = y }; Something like that, but the above syntax is not good.structs, would make this sort of thing very convenient.Sounds complicated.compatible.I think D is aiming more toward status quo remaining largely CHm... Who needs the curent comma operator anyway?Nobody. It has very few uses, and those are questionable: Comma Operator Use 1: putting more than one assignment into a statement controlled by an if without having to use curly braces: if (foo > bar) x = foo, y = bar; which can easily be written thusly, no big deal: if (foo > bar) { x = foo; y = bar; }Comma Operator Use 2: doing some calculation before return int fn() { int x,y; return x = get_x(), y = get_y(), x*x + y*y + 1; } It would be clearer if written like this anyway: int fn() { int x = get_x(); int y = get_y(); return x*x + y*y + 1; }Or you could write it with tuples: int fn() { (int x, int y) = ( get_x(), get_y() ) ; return x*x + y*y + 1; } ..or better yet... int fn() { (int x, int y) = get_x_and_y() ; return x*x + y*y + 1; }Comma Operator Use 3: for loops for (int i = 0, j = 1; i < 10 && j != i; ++i, j = i*3) printf("i = %d, j = %d\n", i, j); One could argue that this for loop is trying to do too much anyway. But the language could easily be extended in a slightly different way: allow statement blocks anywhere a statement is allowed, even in the 3rd section of a for loop: for (int i = 0, j = 1; i < 10 && j != i; { ++i; j = i*3; }) printf("i = %d, j = %d\n", i, j); That's a bad example because ++i, j = i*3 could be written j = ++i*3;Or using tuples... for ( (int i, int j) = (0, 1) ; i < 10 && j != i ; (i,j) = ( i+1, (i+1)*3 ) ) printf("i = %d, j = %d\n", i, j);Anyway the point is, there is not much the comma operator can do that can't easily be expressed some other, more legible way. It would be nice to have comma operator available for something truly useful, like tuples. Sean
Dec 09 2003
How bout this: (a) = someFunc( (int, int, int) = foo(float) ) ? could just makin it more explicit work ?(a) = someFunc(10); Further to that, how would nested functions work? (int) = someFunc(int, int, int) (int, int, int) = foo(float) (a) = someFunc(foo(10.0));Nesting for the time being should not be allowed. The function should return a parameterized rvalue ready for assignment to a suitable lvalue. If a compelling case arises this could be explored.
Dec 02 2003