Thread overview
out default argument of void
Jan 04, 2012
Caligo
Jan 04, 2012
Jesse Phillips
Jan 04, 2012
Simen Kjærås
Jan 04, 2012
Jesse Phillips
Jan 04, 2012
Caligo
Jan 04, 2012
Timon Gehr
Jan 04, 2012
Simen Kjærås
Jan 04, 2012
Ali Çehreli
January 04, 2012
I have a function that looks something like this:

bool fun(double theta, out A a, out B b, out C c){  /* ... */ }

if fun() returns false, then nothing is supposed to be assigned to a, b, c.  If it returns true, then values are assigned to a, b, c.  Also, there are two ways to call fun():  If I'm interested in the return value only, then

1. fun(theta);

otherwise,

2. fun(theta, a, b, c);

Obviously, method #1 won't work because there is no such thing as:

bool fun(double theta, out A a = void, out B b = void, out C c =
void){  /* ... */ }

is there?

So, I have to lose 'out' and use pointers instead:

bool fun(double theta, A* a = null, B* b = null, C* c = null){  /* ... */ }

I don't want to use a variadic function for this either because it's not really a variadic function.

1. Are there any other solutions ?
2. Would it make sense to have 'out default argument of void' in D?
January 04, 2012
On Wednesday, 4 January 2012 at 22:19:28 UTC, Caligo wrote:
> 1. Are there any other solutions ?
> 2. Would it make sense to have 'out default argument of void' in D?

Out parameters are initialized. The declaration you want is:

bool fun(double theta, A a = A.init, B b = B.init, C c = C.init){ /* ... */ }

or, just overload the function for just taking theta.

If A, B, and C are classes then you can use null and not use pointers.
January 04, 2012
On 01/04/2012 11:19 PM, Caligo wrote:
> I have a function that looks something like this:
>
> bool fun(double theta, out A a, out B b, out C c){  /* ... */ }
>
> if fun() returns false, then nothing is supposed to be assigned to a,
> b, c.  If it returns true, then values are assigned to a, b, c.  Also,
> there are two ways to call fun():  If I'm interested in the return
> value only, then
>
> 1. fun(theta);
>
> otherwise,
>
> 2. fun(theta, a, b, c);
>
> Obviously, method #1 won't work because there is no such thing as:
>
> bool fun(double theta, out A a = void, out B b = void, out C c =
> void){  /* ... */ }
>
> is there?
>
> So, I have to lose 'out' and use pointers instead:
>
> bool fun(double theta, A* a = null, B* b = null, C* c = null){  /* ... */ }
>
> I don't want to use a variadic function for this either because it's
> not really a variadic function.
>
> 1. Are there any other solutions ?

Yes. Use overloading.

This would work:

bool fun(double theta, out A a, out B b, out C c){  /* ... */ }
bool fun(double theta){
    A a; B b; C c;
    return fun(theta,a,b,c);
}

Or this:

private bool funImpl(double theta, A* a = null, B* b = null, C* c = null){  /* ... */ }

bool fun(double theta, out A a, out B b, out C c){return funImpl(theta,&a,&b,&c);
bool fun(double theta){return funImpl(theta);}


> 2. Would it make sense to have 'out default argument of void' in D?

void initializer means uninitialized. I don't think that can do what you want.
January 04, 2012
On Wed, 04 Jan 2012 23:19:18 +0100, Caligo <iteronvexor@gmail.com> wrote:

> I have a function that looks something like this:
>
> bool fun(double theta, out A a, out B b, out C c){  /* ... */ }
>
> if fun() returns false, then nothing is supposed to be assigned to a,
> b, c.  If it returns true, then values are assigned to a, b, c.  Also,
> there are two ways to call fun():  If I'm interested in the return
> value only, then
>
> 1. fun(theta);
>
> otherwise,
>
> 2. fun(theta, a, b, c);
>
> Obviously, method #1 won't work because there is no such thing as:
>
> bool fun(double theta, out A a = void, out B b = void, out C c =
> void){  /* ... */ }
>
> is there?
>
> So, I have to lose 'out' and use pointers instead:
>
> bool fun(double theta, A* a = null, B* b = null, C* c = null){  /* ... */ }
>
> I don't want to use a variadic function for this either because it's
> not really a variadic function.
>
> 1. Are there any other solutions ?

A few days ago, I posted this code:



template LRef( T, string f = __FILE__, int l = __LINE__ ) {
    static T LRef;
}

ref T lref( T, string f = __FILE__, int l = __LINE__ )( T value ) {
    LRef!( T, f, l ) = value;
    return LRef!( T, f, l );
}

unittest {
    assert( __traits( compiles, lref(0) = 3 ) );
}



It would allow you to have a throwaway value to use for default
parameters:

void foo( ref int n = lref(0) ) {
}


Also, note that I'm using ref, not out. out parameters are initialized
to their default value upon entering the function, so would not give
the behavior you want.


> 2. Would it make sense to have 'out default argument of void' in D?

No. ref and out are basically non-nullable pointers, and having them
nullable opens a whole barrel of worms.
January 04, 2012
On Wed, 04 Jan 2012 23:40:28 +0100, Jesse Phillips <Jessekphillips+D@gmail.com> wrote:

> On Wednesday, 4 January 2012 at 22:19:28 UTC, Caligo wrote:
>> 1. Are there any other solutions ?
>> 2. Would it make sense to have 'out default argument of void' in D?
>
> Out parameters are initialized. The declaration you want is:
>
> bool fun(double theta, A a = A.init, B b = B.init, C c = C.init){ /* ... */ }

No. ref A a, perhaps, but that again precludes the use of A.init as
default value.
January 04, 2012
On 01/04/2012 02:19 PM, Caligo wrote:
> I have a function that looks something like this:
>
> bool fun(double theta, out A a, out B b, out C c){  /* ... */ }
>
> if fun() returns false, then nothing is supposed to be assigned to a,
> b, c.  If it returns true, then values are assigned to a, b, c.  Also,
> there are two ways to call fun():  If I'm interested in the return
> value only, then
>
> 1. fun(theta);
>
> otherwise,
>
> 2. fun(theta, a, b, c);

How about providing the results always as return values:

import std.exception;

alias int A;
alias int B;
alias int C;

bool fun(double)
{
    return true;
}

struct ABC
{
    A a;
    B b;
    C c;
}

struct FunResult
{
    ABC * abc;

    @property bool isValid() const
    {
        return abc !is null;
    }

    @property A a() const
    {
        enforce(abc);
        return abc.a;
    }

    // etc.
}

FunResult funWithResult(double)
{
    return FunResult(new ABC);
}

void main()
{
    auto isValid = fun(1.1);

    auto result = funWithResult(2.2);
    if (result.isValid) {
        auto use = result.a;
    }
}

Ali

January 04, 2012
On Wed, Jan 4, 2012 at 4:40 PM, Jesse Phillips <Jessekphillips+D@gmail.com> wrote:
>
> Out parameters are initialized. The declaration you want is:
>
> bool fun(double theta, A a = A.init, B b = B.init, C c = C.init){ /* ... */
> }
>

In my case A, B, and C are structs, so that works the way I wanted it. Nice!

It doesn't, however, work with primitive types:

void fun2(int a, out int b = int.init){ }
int a = 32;
fun2(a);  Error: constant 0 is not an lvalue

oh well.
January 04, 2012
On Wednesday, 4 January 2012 at 23:02:24 UTC, Simen Kjærås wrote:
> On Wed, 04 Jan 2012 23:40:28 +0100, Jesse Phillips <Jessekphillips+D@gmail.com> wrote:
>
>> On Wednesday, 4 January 2012 at 22:19:28 UTC, Caligo wrote:
>>> 1. Are there any other solutions ?
>>> 2. Would it make sense to have 'out default argument of void' in D?
>>
>> Out parameters are initialized. The declaration you want is:
>>
>> bool fun(double theta, A a = A.init, B b = B.init, C c = C.init){ /* ... */ }
>
> No. ref A a, perhaps, but that again precludes the use of A.init as
> default value.

Oops, yeah, those should be out parameters which doesn't work. Doesn't that just mean out parameters can't have default values and is not related to void?