Out parameters and initialization
Unknown W. Brackets
unknown at simplemachines.org
Sun Feb 26 16:22:43 PST 2006
Given the following example:
class X
{
int bar;
}
int foo(out X var)
{
var.bar = 5;
assert(var.bar == 5);
}
Look at that, an out parameter - being read? Amazing, I've done the
unthinkable.
If a variable is a pointer, it should be a pointer. Classes, as
reference types, are clear because they are always pointers. However,
consider the following:
import std.stdio;
int main()
{
int x;
test(x);
return 0;
}
void test(out int x)
{
writefln(typeid(typeof(x)));
}
This code clearly identifies x as an int. If it is an int, it should be
an int, and it should always be an int. I mean, that's just common
sense. If an animal is a moose, it should not be a giraffe. We learn
this in kindergarten.
In every other way, out and inout parameters are treated as moose. ONLY
when they receive a default parameter are they being treated as giraffe.
This is inconsistent. They should only ever be treated as one animal:
as a giraffe, or as a moose. There is no girmooffe.
I've really grown quite tired with your patronizing and condescending
tone, and you are reminding me exactly what I dislike about this
newsgroup and therefore D; the people who seem to surround it. The
language seems okay but I honestly remember why I don't use it as often
every time I get in a conversation with one of you people.
-[Unknown]
> On Sun, 26 Feb 2006 14:44:57 -0800, Unknown W. Brackets
> <unknown at simplemachines.org> wrote:
>> Yes, but this is a topic about a bug. We are no longer really talking
>> about the bug.
>>
>> If you used your workaround, you would have:
>>
>> 1. Extra global variables somewhere in memory, which may not be
>> desirable.
>
> True, however you can use the same default global for every parameter of
> the same type provided the 'out' contract of the function does not check
> them (which is something you will know and can work around), eg.
>
> int dontCare;
> int test(out int a = dontCare, out int b = dontCare, out int c =
> dontCare) { ... }
>
> You can do this because the dummy globals are never 'read' by anything
> at any time.
>
>> 2. Uninitialized variables, from what I can tell (out parameters are
>> normally initialized to their default state at the beginning of the
>> function.) This may cause unexpected/hard-to-reproduce bugs.
>
> 'out' and dummy globals do not prevent the init of the out parameter:
>
> import std.stdio;
>
> int global = 5;
>
> void test(out int a = global) {
> writefln(a);
> }
>
> void main()
> {
> writefln(global);
> test();
> }
>
> Output:
> 5
> 0
>
>> 3. Requirements to use synchronized blocks around accesses to the
>> variables
>
> Why? Given that value of an 'out' variable is never 'read' by anyone at
> any time it does not matter what value it has at any given time, or even
> that it has any sensible value at all.
>
> The same cannot be said for 'inout' however. For 'inout' you would need
> to protect access to the global. For 'inout' your points above are
> valid. You would need to protect access to the global, but, as Ivan
> mentioned that may be exactly what you want.
>
> In the end are we arguing about the utility of each set of behaviour or
> the logic of it?
>
> If we're arguing about the logic, my opinion remains that the current
> behaviour is logical given the following rules:
> "out and inout _always_ alias/reference the parameter passed"
> "a default parameter is passed when no parameter is given explicitly"
> "a constant cannot be passed by reference"
>
> In order to implement inout how you describe (as 'in' sometimes) you'd
> need to break rule #1, making the behaviour illogical and inconsistent
> with other instances of 'inout'.
>
> The problem seems mainly to be the perception that a default parameter
> is a default initializer and that is simply incorrect in the general
> case. It is only true for value types passed as 'in' parameters. Take
> for example:
>
> void test(int* a = 5) {} //cannot implicitly convert expression (5) of
> type int to int*
>
> you would never expect that to work, right?
>
> This is essentially identical to:
>
> void test(inout int a = 5) {}
>
> Regan
More information about the Digitalmars-d-bugs
mailing list