www.digitalmars.com         C & C++   DMDScript  

D - Multiple value returns in D?

reply lacs <lacs_member pathlink.com> writes:
I dont see multiple value returns in D. Wouldnt it be nice to finally have it
anywhere else than in scheme? From a logical standpoint,we are already doing it
anyway with reference parameters. Its just that something like (y2,
error)fct(y1, someArg) would be more clear than just fct(y1, someArgs, y2, err).


newbie1654
Apr 21 2004
next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
lacs wrote:

I dont see multiple value returns in D. Wouldnt it be nice to finally have it
anywhere else than in scheme? From a logical standpoint,we are already doing it
anyway with reference parameters. Its just that something like (y2,
error)fct(y1, someArg) would be more clear than just fct(y1, someArgs, y2, err).


newbie1654
  

2.0, but I don't see it in 1.0 as there are too many subtle problems. -- -Anderson: http://badmama.com.au/~anderson/
Apr 21 2004
parent reply lacs <lacs qwerty.ca> writes:
J Anderson wrote:
 lacs wrote:
 
 I dont see multiple value returns in D. Wouldnt it be nice to finally 
 have it
 anywhere else than in scheme? From a logical standpoint,we are already 
 doing it
 anyway with reference parameters. Its just that something like (y2,
 error)fct(y1, someArg) would be more clear than just fct(y1, someArgs, 
 y2, err).


 newbie1654
  

2.0, but I don't see it in 1.0 as there are too many subtle problems.

because of some stack and overloading considerations. However, just making the compiler considere float, float foo(in float, in float); the same as void foo(in float, in float, out float, out float); would not be very complicated. Does it really needs to be more sophisticated then that?
Apr 21 2004
parent reply Derek Parnell <derek psych.ward> writes:
On Wed, 21 Apr 2004 17:50:19 -0400, lacs wrote:

 J Anderson wrote:
 lacs wrote:
 
 I dont see multiple value returns in D. Wouldnt it be nice to finally 
 have it
 anywhere else than in scheme? From a logical standpoint,we are already 
 doing it
 anyway with reference parameters. Its just that something like (y2,
 error)fct(y1, someArg) would be more clear than just fct(y1, someArgs, 
 y2, err).


 newbie1654
  

2.0, but I don't see it in 1.0 as there are too many subtle problems.

because of some stack and overloading considerations. However, just making the compiler considere float, float foo(in float, in float); the same as void foo(in float, in float, out float, out float); would not be very complicated. Does it really needs to be more sophisticated then that?

I too think that the "Multiple Return Value" issue is just one of syntax and not semantics. It is *just* a way of coding in such a way to make it easy for the code reader/maintainer to see that a routine is returning more than one distinct value. The difference would be ... ValA, ValB = foo(inpA, inpB); as opposed to foo(inpA, inpB, ValA, ValB); which is more clear to readers what the routine is actually doing with the variables used. -- Derek 22/Apr/04 10:43:07 AM
Apr 21 2004
next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Derek Parnell wrote:

  ValA, ValB = foo(inpA, inpB);

as opposed to

  foo(inpA, inpB, ValA, ValB);

which is more clear to readers what the routine is actually doing with the
variables used.
  

example, what you presented is valid code ATM! int func() { return 0; } void main() { int a, b; a, b = func(); } Now you could introduce rules to take this out of the language (or change the syntax). It's just one of the subtle bugs and language changes I was talking about to implement such a thing. -- -Anderson: http://badmama.com.au/~anderson/
Apr 21 2004
parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 22 Apr 2004 09:04:07 +0800, J Anderson wrote:

 Derek Parnell wrote:
 
  ValA, ValB = foo(inpA, inpB);

as opposed to

  foo(inpA, inpB, ValA, ValB);

which is more clear to readers what the routine is actually doing with the
variables used.
  

example, what you presented is valid code ATM! int func() { return 0; } void main() { int a, b; a, b = func(); } Now you could introduce rules to take this out of the language (or change the syntax). It's just one of the subtle bugs and language changes I was talking about to implement such a thing.

I'm sorry that I didn't make myself clear. I wasn't suggesting *any* specific syntax, just the concept that a syntax change to support this idea might be worth considering. The example I gave was just to show something - not the precise syntax that D could use. That would need much more discussion yet. -- Derek 22/Apr/04 11:11:09 AM
Apr 21 2004
parent J Anderson <REMOVEanderson badmama.com.au> writes:
Derek Parnell wrote:

I'm sorry that I didn't make myself clear. I wasn't suggesting *any*
specific syntax, just the concept that a syntax change to support this idea
might be worth considering. The example I gave was just to show something -
not the precise syntax that D could use. That would need much more
discussion yet.

  

There are huge threads earlier on this. I don't expect you to read them all but there must be at least a dozen different ways of doing multiple return values. -- -Anderson: http://badmama.com.au/~anderson/
Apr 21 2004
prev sibling parent reply "Unknown W. Brackets" <unknown at.simplemachines.dot.org> writes:
Derek Parnell wrote:
 
   ValA, ValB = foo(inpA, inpB);
 

Not to be annoying, but I don't know that I like that syntax. I think something with parenthesis would be much better... but then, why not just return an array? It's practically the same thing, isn't it? PHP, for example, provides a "array extracting" construct, which works as such: list ($first_element, $second_element) = array(0 => 1, 1 => 2); I believe Perl also has this, basically, except it's like this: array = (1, 2); ($first_element, $second_element) = array; But I think that syntax is ulgy too. I like the "list" construct because it makes it more logical. list (ValA, ValB) = foo(inpA, inpB); -[Unknown]
Apr 21 2004
parent reply Derek Parnell <derek psych.ward> writes:
On Wed, 21 Apr 2004 18:05:04 -0700, Unknown W. Brackets wrote:

 Derek Parnell wrote:
 
   ValA, ValB = foo(inpA, inpB);
 

Not to be annoying, but I don't know that I like that syntax. I think something with parenthesis would be much better... but then, why not just return an array? It's practically the same thing, isn't it?

You are not annoying ;-) I wasn't promoting any specific syntax, just the idea that a syntax change for D that supports multiple return values might be a useful idea.
 PHP, for example, provides a "array extracting" construct, which works 
 as such:
 
 	list ($first_element, $second_element) = array(0 => 1, 1 => 2);
 
 I believe Perl also has this, basically, except it's like this:
 
 	 array = (1, 2);
 	($first_element, $second_element) =  array;
 
 But I think that syntax is ulgy too.  I like the "list" construct 
 because it makes it more logical.
 
 	list (ValA, ValB) = foo(inpA, inpB);
 
 -[Unknown]

And I'm sure there are many others out there too. -- Derek 22/Apr/04 11:13:43 AM
Apr 21 2004
parent reply "Unknown W. Brackets" <unknown at.simplemachines.dot.org> writes:
Derek Parnell wrote:

 On Wed, 21 Apr 2004 18:05:04 -0700, Unknown W. Brackets wrote:
 
 
Derek Parnell wrote:

  ValA, ValB = foo(inpA, inpB);

Not to be annoying, but I don't know that I like that syntax. I think something with parenthesis would be much better... but then, why not just return an array? It's practically the same thing, isn't it?

You are not annoying ;-) I wasn't promoting any specific syntax, just the idea that a syntax change for D that supports multiple return values might be a useful idea.
PHP, for example, provides a "array extracting" construct, which works 
as such:

	list ($first_element, $second_element) = array(0 => 1, 1 => 2);

I believe Perl also has this, basically, except it's like this:

	 array = (1, 2);
	($first_element, $second_element) =  array;

But I think that syntax is ulgy too.  I like the "list" construct 
because it makes it more logical.

	list (ValA, ValB) = foo(inpA, inpB);

-[Unknown]

And I'm sure there are many others out there too.

Sorry, somewhere along there I lost my specific point. That is: Why are multiple return values even needed? How would you return them? Like this: return (a, b); In that case... what is wrong with using an array? The only problem here comes with two different types, like returning an int and a char[]. But, then, if the return types are expected... could a void array be used? -[Unknown]
Apr 21 2004
next sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
Unknown W. Brackets wrote:

 Sorry, somewhere along there I lost my specific point.  That is:

 Why are multiple return values even needed?  How would you return 
 them?  Like this:

 return (a, b);

 In that case... what is wrong with using an array?  The only problem 
 here comes with two different types, like returning an int and a 
 char[].  But, then, if the return types are expected... could a void 
 array be used?

 -[Unknown]

Void is not type safe. -- -Anderson: http://badmama.com.au/~anderson/
Apr 21 2004
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Wed, 21 Apr 2004 18:20:33 -0700, Unknown W. Brackets wrote:

 Derek Parnell wrote:
 
 On Wed, 21 Apr 2004 18:05:04 -0700, Unknown W. Brackets wrote:
 
 
Derek Parnell wrote:

  ValA, ValB = foo(inpA, inpB);

Not to be annoying, but I don't know that I like that syntax. I think something with parenthesis would be much better... but then, why not just return an array? It's practically the same thing, isn't it?

You are not annoying ;-) I wasn't promoting any specific syntax, just the idea that a syntax change for D that supports multiple return values might be a useful idea.
PHP, for example, provides a "array extracting" construct, which works 
as such:

	list ($first_element, $second_element) = array(0 => 1, 1 => 2);

I believe Perl also has this, basically, except it's like this:

	 array = (1, 2);
	($first_element, $second_element) =  array;

But I think that syntax is ulgy too.  I like the "list" construct 
because it makes it more logical.

	list (ValA, ValB) = foo(inpA, inpB);

-[Unknown]

And I'm sure there are many others out there too.

Sorry, somewhere along there I lost my specific point. That is: Why are multiple return values even needed? How would you return them? Like this: return (a, b); In that case... what is wrong with using an array? The only problem here comes with two different types, like returning an int and a char[]. But, then, if the return types are expected... could a void array be used? -[Unknown]

Ok. Not wanting to change D very much, I'd suggest that the current function signature syntax be used. eg.... void foo(int A, int B, out int C, out int D) and then inside the function, again with no changes, the coder would just use normal assignments to the 'out' arguments. The changes would be only involved in how such a function is called. Rather than use the existing syntax (though this would still be available), the coder could call the function thus (and this is just a suggestion so far) ... #(FldA, FldX) = foo( Data_1, Data_2); and the compiler would translate this as if the coder had written ... foo(Data_1, Data_2, FldA, FldX); The compiler maps the arguments by using the function signature from left to right, when it gets an 'out' argument it uses the next parameter from the #(...) list otherwise it uses the parameter from the function call list. The benefit would be clearer (explicit) code that the routine is modifying data. This helps the reader of the code who can then see this without having to search for the function signature somewhere. -- Derek 22/Apr/04 11:21:30 AM
Apr 21 2004
next sibling parent reply Juan C <Juan_member pathlink.com> writes:
I for one don't see where such a thing would be needed. If the values are
related then return a reference to an instance of a class or struct that
contains them. If not, then why are they being returned by the same function?
Apr 21 2004
parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 22 Apr 2004 04:32:27 +0000 (UTC), Juan C wrote:

 I for one don't see where such a thing would be needed. If the values are
 related then return a reference to an instance of a class or struct that
 contains them. If not, then why are they being returned by the same function?

I suspect you have a valid point here. Of course, your point also argues in favour of only ever having, at most, one 'out' argument for a function. It goes roughly like this ... if you need two or more 'out' arguments, they must be related (otherwise why are they being output by the same function), so one should really define a struct or class to contain them, and use that instead. I'm not advocating this, just pointing out that your point relies on the assumption that the returned values *must* be related to each other. Anyhow, even though I can't, I'm sure that somebody can come up with a valid situation where the returned values are not necessarily related. But then I suppose it could be argued that there really should have been multiple function calls (the original function is probably not factored sufficiently). -- Derek 22/Apr/04 2:42:36 PM
Apr 21 2004
parent J Anderson <REMOVEanderson badmama.com.au> writes:
Derek Parnell wrote:

But then I suppose it could be argued that there really should have been
multiple function calls (the original function is probably not factored
sufficiently).
  

you would have to temporarily store some of the values (or of course pass it out by param). -- -Anderson: http://badmama.com.au/~anderson/
Apr 21 2004
prev sibling parent reply Tydr Schnubbis <nobody nowhere.fake> writes:
Derek Parnell wrote:
  > Ok. Not wanting to change D very much, I'd suggest that the current
 function signature syntax be used. eg....
 
   void foo(int A, int B, out int C, out int D) 
 
 and then inside the function, again with no changes, the coder would just
 use normal assignments to the 'out' arguments.
 
 The changes would be only involved in how such a function is called. Rather
 than use the existing syntax (though this would still be available), the
 coder could call the function thus (and this is just a suggestion so far)
 ...
 
    #(FldA, FldX) = foo( Data_1, Data_2);
 
 and the compiler would translate this as if the coder had written ...
 
   foo(Data_1, Data_2, FldA, FldX);
 
 The compiler maps the arguments by using the function signature from left
 to right, when it gets an 'out' argument it uses the next parameter from
 the #(...) list otherwise it uses the parameter from the function call
 list.
 
 The benefit would be clearer (explicit) code that the routine is modifying
 data. This helps the reader of the code who can then see this without
 having to search for the function signature somewhere.
 

Wouldn't you get most of that effect just by requiring the caller to prefix output arguments with 'out' when calling the function, like this? // declare int foo(int a, out char[] s); // call char[] s; int x; x = foo(5, out s); // 'out' required I think maybe C# does it like this. But there's probably some reason unknown to me why this isn't done like this already... Tor
Apr 22 2004
next sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Tydr Schnubbis" <nobody nowhere.fake> wrote in message
news:c696qp$9vn$1 digitaldaemon.com...
 Derek Parnell wrote:
   > Ok. Not wanting to change D very much, I'd suggest that the current
 function signature syntax be used. eg....

   void foo(int A, int B, out int C, out int D)

 and then inside the function, again with no changes, the coder would just
 use normal assignments to the 'out' arguments.

 The changes would be only involved in how such a function is called. Rather
 than use the existing syntax (though this would still be available), the
 coder could call the function thus (and this is just a suggestion so far)
 ...

    #(FldA, FldX) = foo( Data_1, Data_2);

 and the compiler would translate this as if the coder had written ...

   foo(Data_1, Data_2, FldA, FldX);

 The compiler maps the arguments by using the function signature from left
 to right, when it gets an 'out' argument it uses the next parameter from
 the #(...) list otherwise it uses the parameter from the function call
 list.

 The benefit would be clearer (explicit) code that the routine is modifying
 data. This helps the reader of the code who can then see this without
 having to search for the function signature somewhere.

Wouldn't you get most of that effect just by requiring the caller to prefix output arguments with 'out' when calling the function, like this? // declare int foo(int a, out char[] s); // call char[] s; int x; x = foo(5, out s); // 'out' required I think maybe C# does it like this. But there's probably some reason unknown to me why this isn't done like this already...

The reason is sloth, and it doesn't cut it with me. I think one should have to do it ... ... except that this would reduce genericity in templates. But then again, maybe that's a good thing: it might not be desirable for some conformant functions with slight but important semantic differences to be called in the same manner. So, again, I make a cautious suggestion that explicit out (and inout) should be mandatory. Percival Snape
Apr 22 2004
next sibling parent "Ben Hinkle" <bhinkle4 juno.com> writes:
 So, again, I make a cautious suggestion that explicit out (and inout)

 mandatory.

An example of where implicit inout is useful is in the gmp.d wrapper around the C API for gmp. In the C header the data types are arrays of one element of a struct typedef _mpz_struct mpz_t[1]; so that the typical user code looks like mpz_t x; mpz_t a; mpz_t b; ... mpz_add(x, a, b); // x = a+b; (*) I wrote the gmp.d wrapper using structs and inout variables so that the user code ends up looking the same. If the inout had to be explicit I'd probably change the API to use either pointers mpz_add(&x, &a, &b); // x = a+b; (**) or something like mpz_add(out x, inout a, inout b); // x = a+b; (***) This trick that the C API is using is probably pretty rare, though. And I've written D class wrappers with operator overloading that avoid that C layer anyway. Do people prefer (*) or (**) or (***)? -Ben
Apr 22 2004
prev sibling parent Dave Sieber <dsieber spamnot.sbcglobal.net> writes:
"Matthew" <matthew.hat stlsoft.dot.org> wrote:

 So, again, I make a cautious suggestion that explicit out (and inout)
 should be mandatory.

I second that! It is a very nice feature of C#, in that you can read client code and know what the called function is doing with your arguments. It's just better, more understandable code, and that's always a plus. -- dave
Apr 22 2004
prev sibling parent Derek Parnell <derek psych.ward> writes:
On Thu, 22 Apr 2004 21:35:55 +0200, Tydr Schnubbis wrote:

 Derek Parnell wrote:
   > Ok. Not wanting to change D very much, I'd suggest that the current
 function signature syntax be used. eg....
 
   void foo(int A, int B, out int C, out int D) 
 
 and then inside the function, again with no changes, the coder would just
 use normal assignments to the 'out' arguments.
 
 The changes would be only involved in how such a function is called. Rather
 than use the existing syntax (though this would still be available), the
 coder could call the function thus (and this is just a suggestion so far)
 ...
 
    #(FldA, FldX) = foo( Data_1, Data_2);
 
 and the compiler would translate this as if the coder had written ...
 
   foo(Data_1, Data_2, FldA, FldX);
 
 The compiler maps the arguments by using the function signature from left
 to right, when it gets an 'out' argument it uses the next parameter from
 the #(...) list otherwise it uses the parameter from the function call
 list.
 
 The benefit would be clearer (explicit) code that the routine is modifying
 data. This helps the reader of the code who can then see this without
 having to search for the function signature somewhere.
 

Wouldn't you get most of that effect just by requiring the caller to prefix output arguments with 'out' when calling the function, like this? // declare int foo(int a, out char[] s); // call char[] s; int x; x = foo(5, out s); // 'out' required I think maybe C# does it like this. But there's probably some reason unknown to me why this isn't done like this already... Tor

Yeah, that would work too, given that I'm trying to make the act of reading code less error prone. This might even catch some sloppy code writing habits too. -- Derek 23/Apr/04 10:00:48 AM
Apr 22 2004
prev sibling parent Ilya Minkov <minkov cs.tum.edu> writes:
lacs schrieb:

 I dont see multiple value returns in D. Wouldnt it be nice to finally have it
 anywhere else than in scheme? From a logical standpoint,we are already doing it
 anyway with reference parameters. Its just that something like (y2,
 error)fct(y1, someArg) would be more clear than just fct(y1, someArgs, y2,
err).

Scroll down a bit, this question was asked yesterday or so and i answered extensively. -eye
Apr 21 2004