April 22, 2004
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]
April 22, 2004
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/
April 22, 2004
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
April 22, 2004
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?



April 22, 2004
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
April 22, 2004
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).
>  
>
I don't think that could be a valid argument because then it could mean you would have to temporarily store some of the values (or of course pass it out by param).


-- 
-Anderson: http://badmama.com.au/~anderson/
April 22, 2004
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
April 22, 2004
"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






April 22, 2004
> So, again, I make a cautious suggestion that explicit out (and inout)
should be
> 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


April 22, 2004
"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