Jump to page: 1 2 3
Thread overview
Out parameters and initialization
Feb 24, 2006
Thomas Kuehne
Feb 24, 2006
Ivan Senji
Feb 25, 2006
Ivan Senji
Feb 25, 2006
Ivan Senji
Feb 26, 2006
Regan Heath
Feb 26, 2006
Derek Parnell
Feb 26, 2006
Regan Heath
Feb 26, 2006
Regan Heath
Feb 26, 2006
Ivan Senji
Feb 26, 2006
Regan Heath
Feb 26, 2006
Ivan Senji
Feb 26, 2006
Ivan Senji
Feb 26, 2006
Regan Heath
Feb 27, 2006
Ivan Senji
Feb 27, 2006
Regan Heath
Feb 27, 2006
Ivan Senji
Feb 27, 2006
Derek Parnell
Feb 27, 2006
Ivan Senji
February 20, 2006
The spec says:

out parameters are set to the default initializer for the type of it.

Which makes perfect sense, and works just fine.  The trick comes in when I try some parameter initialization.  This really weirded me out at first.  Example:

int main()
{
        uint i = 0;
        test(i);

        return 0;
}

void test(out uint i = 5)
{
        assert(i == 5);
}

It seems to me that I should either get an error from the compiler, or this should compile and run without any assertions failing.  However, the assert on line 11 does not pass, as of DMD 0.147.

Either way, I would suggest the sentence in the spec be clarified (and the grammar buffed), for example:

out parameters are always set to the default initializer for their type.  Using an initializer on an out parameter is an error.

Or:

out parameters are always set to the default initializer for their type, unless they have an explicit initializer (but regardless of the parameters initial value.)

I couldn't find this reported before, but if it has been please forgive the duplicate.

Hope that's helpful,
-[Unknown]
February 24, 2006
Unknown W. Brackets schrieb am 2006-02-20:
> The spec says:
>
> out parameters are set to the default initializer for the type of it.
>
> Which makes perfect sense, and works just fine.  The trick comes in when I try some parameter initialization.  This really weirded me out at first.  Example:
>
> int main()
> {
>          uint i = 0;
>          test(i);
>
>          return 0;
> }
>
> void test(out uint i = 5)
> {
>          assert(i == 5);
> }
>
> It seems to me that I should either get an error from the compiler, or this should compile and run without any assertions failing.  However, the assert on line 11 does not pass, as of DMD 0.147.
>
> Either way, I would suggest the sentence in the spec be clarified (and the grammar buffed), for example:
>
> out parameters are always set to the default initializer for their type.
>   Using an initializer on an out parameter is an error.
>
> Or:
>
> out parameters are always set to the default initializer for their type, unless they have an explicit initializer (but regardless of the parameters initial value.)

Where exactly are default parameters for functions documented?
changelog:
| Added default arguments to function parameters. Semantics are like C++.

functions:
| A functions parameter's default value is not inherited.

C++ has - as far as I'm aware - no out keyword.

Added to DStress as http://dstress.kuehne.cn/undefined/default_argument_10.d

Thomas


February 24, 2006
I may have been unclear, but this is the thing I was most specifically referencing; that there was no defined behavior for this in the spec's wording.

As for default parameters (initializers) being defined at all, that's in the declarations page:

Parameter:
        Declarator
        Declarator = AssignExpression
        InOut Declarator
        InOut Declarator = AssignExpression

This presumably implies it has the same semantics as DeclaratorInitializer, but there's no explicit definition.  Further, it is interesting to me that AssignExpression is used instead of Initializer; this may actually mean different semantics (and not just that you cannot use array/struct literals and void here.)

-[Unknown]


> Where exactly are default parameters for functions documented?
February 24, 2006
Unknown W. Brackets wrote:
> The spec says:
> 
> out parameters are set to the default initializer for the type of it.
> 
> Which makes perfect sense, and works just fine.  The trick comes in when I try some parameter initialization.  This really weirded me out at first.  Example:
> 
> int main()
> {
>         uint i = 0;
>         test(i);
> 
>         return 0;
> }
> 
> void test(out uint i = 5)
> {
>         assert(i == 5);
> }
> 

Oops, missed this thread before.

Actually it kind of makes sence to me that this doesn't work.

But this does work, and is IMO a great feature:

int globalI = 0;

int main()
{
        uint i = 0;
        test();
	//globalI is now 5

        return 0;
}

void test(out uint i = globalI)
{
	i = 5;
        assert(i == 5);
}
February 25, 2006
Where is that in the spec?  Why is that logical?

-[Unknown]


> Unknown W. Brackets wrote:
>> The spec says:
>>
>> out parameters are set to the default initializer for the type of it.
>>
>> Which makes perfect sense, and works just fine.  The trick comes in when I try some parameter initialization.  This really weirded me out at first.  Example:
>>
>> int main()
>> {
>>         uint i = 0;
>>         test(i);
>>
>>         return 0;
>> }
>>
>> void test(out uint i = 5)
>> {
>>         assert(i == 5);
>> }
>>
> 
> Oops, missed this thread before.
> 
> Actually it kind of makes sence to me that this doesn't work.
> 
> But this does work, and is IMO a great feature:
> 
> int globalI = 0;
> 
> int main()
> {
>         uint i = 0;
>         test();
>     //globalI is now 5
> 
>         return 0;
> }
> 
> void test(out uint i = globalI)
> {
>     i = 5;
>         assert(i == 5);
> }
February 25, 2006
Unknown W. Brackets wrote:
> Where is that in the spec?  Why is that logical?

In the spec? As far as I know it isn't (at least I didn't see it anywhere).

Logical because:

void func(in int x = 7); means this is an input value and if I don't suply one the default value will be 7.

void func(out int x = globalX);
out tels us the value of x will be changed, the default value says if I don't suply an argument change by default the value of variable globalX.

If you did something like:
void func(out int x = 7)
{
  x = 11;
}

the compiler will complain about 7 not being an l-value.
It is the same reason why you can't call the above function like func(11); 11 can not be assigned to.

The above effect can be/(should be able to be) achieved by
typedef int int7 = 7; or something like this.

I hope this is the way it is ment to work  and not some crazy bug because I'm really starting to like this feature.

> 
February 25, 2006
Honestly, I understand the usefulness and where you're coming from, but if that's really intended it makes absolutely no logical sense to me.

That would be like this working:

int i = 0;
int j = i;

j = 5;
assert(i == 5);

I realize that out is a reference/pointer type thing (automatically), but if there's no * there or anything, I don't want other variables to change.  It completely contradicts everything else in the language to me.... maybe it's just me, though.

-[Unknown]


> Unknown W. Brackets wrote:
>> Where is that in the spec?  Why is that logical?
> 
> In the spec? As far as I know it isn't (at least I didn't see it anywhere).
> 
> Logical because:
> 
> void func(in int x = 7); means this is an input value and if I don't suply one the default value will be 7.
> 
> void func(out int x = globalX);
> out tels us the value of x will be changed, the default value says if I don't suply an argument change by default the value of variable globalX.
> 
> If you did something like:
> void func(out int x = 7)
> {
>   x = 11;
> }
> 
> the compiler will complain about 7 not being an l-value.
> It is the same reason why you can't call the above function like func(11); 11 can not be assigned to.
> 
> The above effect can be/(should be able to be) achieved by
> typedef int int7 = 7; or something like this.
> 
> I hope this is the way it is ment to work  and not some crazy bug because I'm really starting to like this feature.
> 
>>
February 25, 2006
Unknown W. Brackets wrote:
> Honestly, I understand the usefulness and where you're coming from, but if that's really intended it makes absolutely no logical sense to me.

And I honestly understand what behaviour you want. It happens that I accidently found this behaviour and find it usefull.

> 
> That would be like this working:
> 
> int i = 0;
> int j = i;
> 
> j = 5;
> assert(i == 5);

Well with this I don't agree. int here isn't a reference type. (And I know that you didn't really mean this as an equivalent example)

> 
> I realize that out is a reference/pointer type thing (automatically), but if there's no * there or anything, I don't want other variables to change.  It completely contradicts everything else in the language to me.... maybe it's just me, though.

I see it like this (maybe I'm repeating my self)

void func(in int a = 5)
//func(), use default in value of 5

Default values are ment for cases when *no arguments* are specified:

void func(out int a = 7)
{
  a = 3;
}

func();

//what is the above code doing? Assigning 3 to what? To 7? That isn't possible because 7 is a constant.

The idea that a function
void func(out int a = 7){}
when called like this: func(b);
is assigning 7 to b, contradicts the meaning of default in arguments.
February 26, 2006
I understand it is useful.  Indeed, the following, if it worked, could possibly also be useful:

label:
// Never executed.
x = 1;

comefrom label;

That does not make it logical or consistent.  It makes it confusing and inconsistent.  Utility is not at all my concern.

In other words, you're essentially saying that this makes sense:

var2 = 2;
var1 = var2;
var1 = 1;
assert(var2 == 1);

If it were the other way around (var2 = var1) or if either variable had anything to do with C-style references or pointers, I might agree with you.  But even if they were classes, this would make no sense whatsoever.

It simply is not consistent with the rest of the language.  If it's going to work that way, it should do so everywhere.

-[Unknown]


> Unknown W. Brackets wrote:
>> Honestly, I understand the usefulness and where you're coming from, but if that's really intended it makes absolutely no logical sense to me.
> 
> And I honestly understand what behaviour you want. It happens that I accidently found this behaviour and find it usefull.
> 
>>
>> That would be like this working:
>>
>> int i = 0;
>> int j = i;
>>
>> j = 5;
>> assert(i == 5);
> 
> Well with this I don't agree. int here isn't a reference type. (And I know that you didn't really mean this as an equivalent example)
> 
>>
>> I realize that out is a reference/pointer type thing (automatically), but if there's no * there or anything, I don't want other variables to change.  It completely contradicts everything else in the language to me.... maybe it's just me, though.
> 
> I see it like this (maybe I'm repeating my self)
> 
> void func(in int a = 5)
> //func(), use default in value of 5
> 
> Default values are ment for cases when *no arguments* are specified:
> 
> void func(out int a = 7)
> {
>   a = 3;
> }
> 
> func();
> 
> //what is the above code doing? Assigning 3 to what? To 7? That isn't possible because 7 is a constant.
> 
> The idea that a function
> void func(out int a = 7){}
> when called like this: func(b);
> is assigning 7 to b, contradicts the meaning of default in arguments.
February 26, 2006
On Sat, 25 Feb 2006 16:21:23 -0800, Unknown W. Brackets <unknown@simplemachines.org> wrote:
> That does not make it logical or consistent.  It makes it confusing and inconsistent.  Utility is not at all my concern.

Ok, so lets look at the consistency of this.

> In other words, you're essentially saying that this makes sense:
>
> var2 = 2;
> var1 = var2;
> var1 = 1;
> assert(var2 == 1);

No, he's saying that this makes sense:

void foo(inout int var1) { var1 = 1; }

int var2 = 2;
foo(var2);
assert(var2 == 1);

Remember, 'inout' aliases the variable you pass, the parameter 'var1' is another name for the variable 'var2'.


So, when you write:

void foo(inout int var1 = 7)

what are you saying?

Lets start with what a default parameters means, in this case:

void foo(int var1 = 7) {}

says, if I do not get passed a variable, pass 7, in other words:

foo();

is called as:

foo(7);

Agreed?


Therefore:

void foo(inout int var1 = 7)

says, if I do not get passed a variable, pass 7, meaning:

foo();

is called as:

foo(7);

Agreed?


Now, as well all know you cannot pass '7' as inout because you cannot alias '7'.

What I am trying to show here is that default parameters are behaving both logically and consistently, they always mean: "If I do not get passed a variable, pass X" where X is the default parameter value supplied.

Further, 'inout' is behaving both logically and consistently, in all cases it aliases the parameter which is passed.


The behaviour of 'in'+'default parameter' is not the same as 'inout'+'default parameter' but why should it be? IMO one is an apple and the other an orange.

Regan
« First   ‹ Prev
1 2 3