Should out/ref parameters require the caller to specify out/ref like in C#?

WebFreak001 via Digitalmars-d digitalmars-d at puremagic.com
Sun May 28 10:54:30 PDT 2017


Imagine you wrote a function

void foo(ref int a) {
   if (std.random.uniform(0, 10) == 0)
     a = 0;
   // Actual code doing something
}

in your API you didn't document that this will change `a` (or we 
will assume the user simply didn't read because you would never 
do something like this).

The user now calls the code in his program, probably doesn't know 
that foo takes a as ref and because it's his first time using the 
function he doesn't expect it to either.

void main(string[] args) {
   int input = args[1].to!int + 1;
   writeln("Processing for ", input);
   foo(input);
   writeln(100 / input); // idk, it will crash if input == 0 though
}

Now his code will occasionally crash but the user can't figure 
out why and can't always reproduce it. Imagine the code is 
somewhere deep inside event handlers from some GUI library or 
recursive calls too.

Should the language spec say that those functions should get 
called with `foo(ref input);` so that surprises like this where 
the user doesn't check the docs/implementation can't happen (like 
in C#)?

I think the user should be enforced to use foo(ref input) instead 
of foo(input) as it greatly increases understanding of the code 
on the caller side and another advantage is that programs 
analyzing the AST can better understand if the argument is unused 
(DScanner could use this for example).

On the other hand a lot of code has been written without this 
already and especially a lot of UFCS code would break with this 
like for example functions acting like member functions of the 
ref argument. A fix for this might be just implying the ref you 
would add on an argument if you use UFCS but I'm not sure if that 
is really a good idea.

This post is just an idea because I think it can result in really 
confused users and that the usage both by library developer and 
user of out/ref in general is kind of bad by design because it 
will just imply it and it won't be visible in the code. 
Especially when changing the API this will result in many runtime 
errors that need to be discovered if the user doesn't read the 
changelog.

Especially because this would break a lot of code I don't really 
expect anything to happen but maybe this could be taken into 
account when D3 will be designed or be added in some optional DIP 
that can be used using a compiler flag?


More information about the Digitalmars-d mailing list