February 26, 2006
On Sun, 26 Feb 2006 12:56:04 +1100, Regan Heath <regan@netwin.co.nz> wrote:

> 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.

This makes a lot of sense to me.

-- 
Derek Parnell
Melbourne, Australia
February 26, 2006
If that is the meaning, some symbol should be used to indicate that there is a reference being made.

I don't think, personally, it makes any sense to say that in is a replacement for what might be passed.  It is much more like an initializer, which would never behave in that way.  To me, it is unclear and unlike the rest of the language to do as you suggest.

Your suggestion separates the logic of parameter defaulting from initialization completely, but they share the same syntax (as they share again with assignment.)  I think this is, at best, unclear and clumsy. At worst, it is obviously inconsistent and confusing.

But that is more of a philosophical debate, and that will be for Walter to answer, ultimately.  My point is that there is a bug here, nonetheless.

Regardless of what you are saying, why should my initial example compile?  It should either work as initialization, or not compile.  It should not compile and do nothing.  This is also unclear and inconsistent.

-[Unknown]


> 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
February 26, 2006
On Sat, 25 Feb 2006 18:58:44 -0800, Unknown W. Brackets <unknown@simplemachines.org> wrote:
> If that is the meaning, some symbol should be used to indicate that there is a reference being made.

The symbols 'inout' and 'out' indicate an alias/reference is being made.

> I don't think, personally, it makes any sense to say that in is a replacement for what might be passed.  It is much more like an initializer, which would never behave in that way.  To me, it is unclear and unlike the rest of the language to do as you suggest.

I didn't mean to suggest that 'in' was a replacement for what is passed, but rather that the default initialiser is a replacement for what _isn't_ passed.

> Your suggestion separates the logic of parameter defaulting from initialization completely, but they share the same syntax (as they share again with assignment.)  I think this is, at best, unclear and clumsy. At worst, it is obviously inconsistent and confusing.

I think you make a valid point here. default parameters, and assignment (which initialization is essentially) share the same syntax, they both use '='. It does suggest that a default parameter is an initializer, when in fact, I believe it's not that at all. That same syntax, '=', is likely the cause of this thread :)

> But that is more of a philosophical debate, and that will be for Walter to answer, ultimately.  My point is that there is a bug here, nonetheless.

I agree, my idea at the solution is below.

> Regardless of what you are saying, why should my initial example compile? should not compile, it shouldIt should either work as initialization, or not compile.  It should not compile and do nothing.  This is also unclear and inconsistent.

Your first example compiles because you are passing a parameter to all calls of 'test' and therefore the default parameter is never used. However, this for example:

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

void main()
{
	uint i;
	test(i); //compiles
	test();  //cast(uint)5 is not an lvalue
}

Will not compile because the default parameter is required for the 2nd call to 'test' and '5' is not an lvalue (cannot be aliased).

The solution: I think it would be fair to ask for the compiler to error on:

  void test(out uint i = 5)

regardless of whether the default parameter is ever required, simply because it will never be legal to have a non lvalue default parameter to an 'out' or 'inout' parameter. At the same time perhaps this should remain valid:

uint globalVar;
void test(out uint i = globalVar) {}

because I can imagine some useful things you can do with this.

What do you think Walter?

Regan

> -[Unknown]
>
>
>> 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

February 26, 2006
On Sun, 26 Feb 2006 17:30:09 +1300, Regan Heath <regan@netwin.co.nz> wrote:
> I didn't mean to suggest that 'in' was a replacement for what is passed, but rather that the default initialiser is a replacement for what _isn't_ passed.

Oops, here I am muddying the waters, "default initialiser" should read "default parameter".

Regan
February 26, 2006
Except aliases and typedefs (exactly, as I could tell, for the reason of consistency) do not use an = sign.  If they did, it would be strange and inconsistent.  I am very glad they do not.

Personally, I think = should be disallowed entirely for out parameters, and should work on inout parameters in the same way as it does for in ones.  This would stay logical.

If out int i = 5 should not compile when no parameter is passed, it should not compile when a parameter is passed - as you said.  I think the usefulness of global variables, especially considering thread safety, would only grow confusing in actual and practical use.

-[Unknown]


> On Sat, 25 Feb 2006 18:58:44 -0800, Unknown W. Brackets <unknown@simplemachines.org> wrote:
>> If that is the meaning, some symbol should be used to indicate that there is a reference being made.
> 
> The symbols 'inout' and 'out' indicate an alias/reference is being made.
> 
>> I don't think, personally, it makes any sense to say that in is a replacement for what might be passed.  It is much more like an initializer, which would never behave in that way.  To me, it is unclear and unlike the rest of the language to do as you suggest.
> 
> I didn't mean to suggest that 'in' was a replacement for what is passed, but rather that the default initialiser is a replacement for what _isn't_ passed.
> 
>> Your suggestion separates the logic of parameter defaulting from initialization completely, but they share the same syntax (as they share again with assignment.)  I think this is, at best, unclear and clumsy. At worst, it is obviously inconsistent and confusing.
> 
> I think you make a valid point here. default parameters, and assignment (which initialization is essentially) share the same syntax, they both use '='. It does suggest that a default parameter is an initializer, when in fact, I believe it's not that at all. That same syntax, '=', is likely the cause of this thread :)
> 
>> But that is more of a philosophical debate, and that will be for Walter to answer, ultimately.  My point is that there is a bug here, nonetheless.
> 
> I agree, my idea at the solution is below.
> 
>> Regardless of what you are saying, why should my initial example compile? should not compile, it shouldIt should either work as initialization, or not compile.  It should not compile and do nothing.  This is also unclear and inconsistent.
> 
> Your first example compiles because you are passing a parameter to all calls of 'test' and therefore the default parameter is never used. However, this for example:
> 
> void test(out uint i = 5)
> {
>     assert(i == 5);
> }
> 
> void main()
> {
>     uint i;
>     test(i); //compiles
>     test();  //cast(uint)5 is not an lvalue
> }
> 
> Will not compile because the default parameter is required for the 2nd call to 'test' and '5' is not an lvalue (cannot be aliased).
> 
> The solution: I think it would be fair to ask for the compiler to error on:
> 
>   void test(out uint i = 5)
> 
> regardless of whether the default parameter is ever required, simply because it will never be legal to have a non lvalue default parameter to an 'out' or 'inout' parameter. At the same time perhaps this should remain valid:
> 
> uint globalVar;
> void test(out uint i = globalVar) {}
> 
> because I can imagine some useful things you can do with this.
> 
> What do you think Walter?
> 
> Regan
> 
>> -[Unknown]
February 26, 2006
Unknown W. Brackets wrote:
> Except aliases and typedefs (exactly, as I could tell, for the reason of consistency) do not use an = sign.  If they did, it would be strange and inconsistent.  I am very glad they do not.
> 
> Personally, I think = should be disallowed entirely for out parameters, and should work on inout parameters in the same way as it does for in ones.  This would stay logical.
> 
> If out int i = 5 should not compile when no parameter is passed, it should not compile when a parameter is passed - as you said.  

No, it should never compile.

> I think the usefulness of global variables, especially considering thread safety, would only grow confusing in actual and practical use.

Maybe, but noone is stoping you from implementing thread safe access to global variable if thread safety is what you need.
February 26, 2006
On Sat, 25 Feb 2006 21:02:30 -0800, Unknown W. Brackets <unknown@simplemachines.org> wrote:
> Personally, I think = should be disallowed entirely for out parameters, and should work on inout parameters in the same way as it does for in ones.  This would stay logical.

You realise 'inout' aliases the parameter in the same was as 'out' does?

Regan
February 26, 2006
I'm thinking from the "in-side".  In my mind, if I leave off an out or inout parameter, I want the result to go nowhere (but might still expect the variable to exist in the function.)  I don't see how this isn't logical, but I can understand how you'd disagree.

You do seem to disagree; to make us both happy, perhaps only in should have default parameters allowed.

-[Unknown]


> On Sat, 25 Feb 2006 21:02:30 -0800, Unknown W. Brackets <unknown@simplemachines.org> wrote:
>> Personally, I think = should be disallowed entirely for out parameters, and should work on inout parameters in the same way as it does for in ones.  This would stay logical.
> 
> You realise 'inout' aliases the parameter in the same was as 'out' does?
> 
> Regan
February 26, 2006
Unknown W. Brackets wrote:
> I'm thinking from the "in-side".  In my mind, if I leave off an out or inout parameter, I want the result to go nowhere (but might still expect the variable to exist in the function.)  I don't see how this isn't logical, but I can understand how you'd disagree.

If you don't want a result the solution is easy:

void func(in int x = 7)

func();
All conditions satisfied:
* result is going nowhere
* var exists in a function
* it's value is 7

The point is: if you don't need a result, then what you probably want is in and not out/inout. Out is for something else.
February 26, 2006
Obviously that has nothing to do with what I meant.

Consider:

int foo(out C x, out C y, out C z);

It is possible I may not want to specify a y or a z.  I may however still want the return value and x.  In other parts of my code, I may want x and y, or all three.  Only in some places will I not want z or y.

You clearly misunderstood me.  Using in has absolutely nothing to do with this.

Currently, a workaround would be:

int foo(out C x)
{
   C dummy1, dummy2;
   return foo(x, dummy1, dummy2);
}

But this really is going to the side a bit of the topic.

-[Unknown]


> Unknown W. Brackets wrote:
>> I'm thinking from the "in-side".  In my mind, if I leave off an out or inout parameter, I want the result to go nowhere (but might still expect the variable to exist in the function.)  I don't see how this isn't logical, but I can understand how you'd disagree.
> 
> If you don't want a result the solution is easy:
> 
> void func(in int x = 7)
> 
> func();
> All conditions satisfied:
> * result is going nowhere
> * var exists in a function
> * it's value is 7
> 
> The point is: if you don't need a result, then what you probably want is in and not out/inout. Out is for something else.