Thread overview | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
July 24, 2012 Optional extra return value? Multiple return values with auto? | ||||
---|---|---|---|---|
| ||||
How I can return multiple values in D, but one of them being optional? I tried the 'out' hack to achieve multiple return values, but it didn't accepted a default argument: it needed a lvalue in the calling function. In Lua, for example, one can do: function foo(input) -- calculations -- return result, iterations_needed end a, stats = foo() or, if you are only interested in the result: a = foo() -- the second return is automatically discarded. Do I really have to duplicate the function, in order to achieve this? Also, is there some way to use auto with multiple returns? Like: bool bar(out ulong output){ output = 0 ; return true;} auto check = bar(auto num); // error Right now, I need to declarate num outside the function, and thus I can't use the auto keyword. |
July 24, 2012 Re: Optional extra return value? Multiple return values with auto? | ||||
---|---|---|---|---|
| ||||
Posted in reply to ReneSac | On 07/23/2012 08:25 PM, ReneSac wrote:
> How I can return multiple values in D, but one of them being optional? I
> tried the 'out' hack to achieve multiple return values, but it didn't
> accepted a default argument: it needed a lvalue in the calling function.
Like in C and C++, functions in D can also have a single return value. The most common workaround in C and C++ has been an out parameter (pointer in C and pointer or reference in C++).
The options that I can think of:
- Return a struct (or a class) where one of the members is not filled-in
- Similarly, return a tuple
- Use an out parameter, which can have a default lvalue:
int g_default_param;
void foo(ref int i = g_default_param)
{
if (&i == &g_param) {
// The caller is not interested in 'i'
} else {
// The caller wants 'i'
i = 42;
}
}
void main()
{
foo();
int i;
foo(i);
assert(i == 42);
}
- Use some template trick where the caller specifies what he wants:
result = foo();
complex_result = foo!with_iterations_needed();
Thinking back, perhaps because C and C++ don't provide multiple return values, I never missed them. Although they were nice when coding in Python. :)
Ali
|
July 24, 2012 Re: Optional extra return value? Multiple return values with auto? | ||||
---|---|---|---|---|
| ||||
Posted in reply to ReneSac | On Tuesday, 24 July 2012 at 03:25:55 UTC, ReneSac wrote:
>
> Do I really have to duplicate the function, in order to achieve this?
>
In a nutshell, yes. Or else resort to bizarre sorcery such as may rot the very heart from one's chest (or template ninjitsu, whatever). But is it really so bad?
bool foo ( byte[] data, out int stats ) {
// do a bunch of stuff
}
bool foo ( byte[] data ) {
int dummy;
return foo( data, dummy );
}
One could possibly put together a template that automates this... heck, here's a quick and dirty implementation of such:
##############################
import std.stdio ,
std.traits ;
template DummyLast ( alias Func ) {
ReturnType!Func DummyLast ( ParameterTypeTuple!Func[ 0 .. $ - 1 ] args ) {
ParameterTypeTuple!Func[ $ - 1 ] dummy;
return Func( args, dummy );
}
}
bool foo ( byte[] data, out int stats ) {
stats = 42;
return true;
}
alias DummyLast!foo foo;
void main () {
byte[] data;
bool result;
int stats;
result = foo( data, stats );
writeln( result, ' ', stats );
result = false;
stats = 0;
result = foo( data );
writeln( result, ' ', stats );
}
##############################
-- Chris NS
|
July 24, 2012 Re: Optional extra return value? Multiple return values with auto? | ||||
---|---|---|---|---|
| ||||
Posted in reply to ReneSac | Am 24.07.2012 05:25, schrieb ReneSac: I whish there was: auto foo() { return Tuple!("foo", "bar", 1, new Custum()); } void main() { auto (s1, s2, i, c) = foo(); } |
July 24, 2012 Re: Optional extra return value? Multiple return values with auto? | ||||
---|---|---|---|---|
| ||||
Posted in reply to ReneSac | On Tuesday, 24 July 2012 at 03:25:55 UTC, ReneSac wrote:
> How I can return multiple values in D, but one of them being optional?
One of the ways to to it is to return a tuple with your arguments, where the last item of the tuple is a Nullable of the optional element:
import std.stdio, std.typecons;
Tuple!(int, double, Nullable!int) foo(bool b) {
if (b)
return tuple(5, 1.5, Nullable!int(1));
else
return tuple(10, 2.5, Nullable!int());
}
void main() {
writeln(foo(false)[2]); // enforcement failed
}
Bye,
bearophile
|
July 24, 2012 Re: Optional extra return value? Multiple return values with auto? | ||||
---|---|---|---|---|
| ||||
Posted in reply to David | On Tuesday, 24 July 2012 at 08:56:21 UTC, David wrote:
> Am 24.07.2012 05:25, schrieb ReneSac:
>
> I whish there was:
>
> auto foo() {
> return Tuple!("foo", "bar", 1, new Custum());
> }
>
> void main() {
> auto (s1, s2, i, c) = foo();
> }
I think the main blocker to something like that right now is the compiler's ability to detect and guarantee that the returned tuple will always be a specific series of types (or at least implicitly convertible to a common series). And in order for that, tuples would, I imagine, need to be a part of the language proper. If I'm wrong about that last requirement, then I'm honestly not sure what the main obstacle to this is.
-- Chris NS
|
July 24, 2012 Re: Optional extra return value? Multiple return values with auto? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris NS | It seems forum.dlang.org hides my first answer, I don't know why: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=37708 Bye, bearophile |
August 11, 2012 Re: Optional extra return value? Multiple return values with auto? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Tuesday, 24 July 2012 at 05:30:49 UTC, Ali Çehreli wrote: > The options that I can think of: > > - Return a struct (or a class) where one of the members is not filled-in > > - Similarly, return a tuple This is awkward, and doesn't look good for performance. > > - Use an out parameter, which can have a default lvalue: > > int g_default_param; > > void foo(ref int i = g_default_param) > { > if (&i == &g_param) { > // The caller is not interested in 'i' > > } else { > // The caller wants 'i' > i = 42; > } > } > > void main() > { > foo(); > > int i; > foo(i); > assert(i == 42); > } This is not working inside a class. I'm not sure what default value I should put when I don't know the type entered: class a (T) { T dummy = T.init; bool foo(int a, out T optional = dummy) { return true; } } void main () { auto c = new a!uint(); c.foo(5); } I get the following error: Error: need 'this' to access member dummy |
August 11, 2012 Re: Optional extra return value? Multiple return values with auto? | ||||
---|---|---|---|---|
| ||||
Posted in reply to ReneSac | On 08/11/2012 03:48 PM, ReneSac wrote: > On Tuesday, 24 July 2012 at 05:30:49 UTC, Ali Çehreli wrote: >> - Use an out parameter, which can have a default lvalue: >> >> int g_default_param; >> >> void foo(ref int i = g_default_param) >> { >> if (&i == &g_param) { >> // The caller is not interested in 'i' >> >> } else { >> // The caller wants 'i' >> i = 42; >> } >> } >> >> void main() >> { >> foo(); >> >> int i; >> foo(i); >> assert(i == 42); >> } > > This is not working inside a class. I'm not sure what default value I > should put when I don't know the type entered: > > class a (T) { > T dummy = T.init; > bool foo(int a, out T optional = dummy) > { > return true; > } > } > > void main () { > auto c = new a!uint(); > c.foo(5); > } > > I get the following error: > > Error: need 'this' to access member dummy > I am not a fan of this solution either. To make the code to compile, define dummy as static: static T dummy = T.init; // <-- this works That way there will be just one copy for the entire type, instead of one copy per object. I also tried to define it as immutable but the following line fails to compile: static immutable T dummy = T.init; // <-- compilation error I thought that a solution would be to define 'static this()': class a (T){ static immutable T dummy; static this() { dummy = T.init; } bool foo(int a, out T optional = dummy) { // <-- compilation error on this line return true; } } Still fails to compile: Error: cast(uint)dummy is not an lvalue The error is on the line that I have pointed in the code. I think this is a compiler bug. T is not a reference type and 'cast(uint)dummy' not being an lvalue should not matter. I tried an enum too but a different error on the same line: static enum T dummy = T.init; Error: constant 0u is not an lvalue Ali |
August 11, 2012 Re: Optional extra return value? Multiple return values with auto? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | There is no compiler bug. You cannot pass immutable/rvalue by reference to mutable. |
Copyright © 1999-2021 by the D Language Foundation