View mode: basic / threaded / horizontal-split · Log in · Help
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?
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?
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?
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?
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?
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?
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?
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?
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?
There is no compiler bug. You cannot pass immutable/rvalue by reference
to mutable.
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home