www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Ouput-UFCS proposal: void fun(A a,ref B b) <=> B fun(A a);

reply "timotheecour" <thelastmammoth gmail.com> writes:
I'd like to suggest the following feature that extends UFCS to 
output arguments, hence the name Output-UFCS.

in short:

1) given a function "void fun(A a, ref B b);" (0 or more 
arguments before b)

2) The proposal is to always allow the following expression: 
"auto b=fun(a);"  which the compiler interprets as:

2.1) "OutputType b=fun(a);" if there's a currently compatible 
function call (eg OutputType fun(A a);) (ie the current behavior 
takes precedence).

2.1) or if no such function call is compatible, it'll rewrite it 
under the hood as:
"B b; fun(a,b);"



----------------
Notes:

N0) The obvious advantage is remove BOILERPLATE code. Here's a 
common case:
N0.1) void fun(int n , ref double[]b){b.length=n; b[]=0;}
N0.2) double[] fun(int n){double[]b; fun(n,b); return b;}
N0.2 is needed for convenience for client code, but N0.1 is 
needed for optimization in certain cases where an existing b can 
be reused, thus avoiding allocations, etc. That's very common.

N1) More generally, fun() could be a free function or a 
struct/class method, be templated or not, have any number of 
arguments before b (including 0).

N2) this plays nicely with existing UFCS conversions: eg: the 
following are equivalent for a free function "void fun(A a,ref B 
b)": (unless some of those are already defined in the code, in 
which case they take precedence):

the expression "auto b=fun(a)" is rewritten as "B b; fun(a,b)"  
//OUFCS
the expression "auto b=a.fun()" is rewritten as "B b; a.fun(b)" 
//OUFCS
the expression "a.fun(b)" might be rewritten as "fun(a,b)" under 
UFCS (unless fun is already a member function, in accordance to 
UFCS rules).

with no arg before b: "void fun(ref B b)" :
the expression "auto b=fun()" is rewritten as "B b; fun(b)"  
//OUFCS

N3) There are other cases in which we can allow the conversion to 
happen:

N3.1) "auto b=fun(a);" (disccussed above)

N3.2) "B b=fun(a);" (same as above; we could also decide to have 
a warning or CT error in there's an incompatible existing 
function OutputType fun(A a); where OutputType doesn't implicitly 
convert to B, but that's optional.)

N3.3) "C b=fun(a);" : same as above, but the attempted rewriting 
could look like:
"C b; fun(a,b);" first, or "B b_temp; fun(a,b_temp); b=b_temp;" 
second

N3.4) expression involving fun(a), eg: "expr(fun(a),...)": 
rewritten as "expr(fun_temp(a),...)"
with the following function generated:
B fun_temp(A a){ B b; fun(a,b);  return b; }

N3.4) finally if anyone's unhappy with introducing too much 
magic, we can always introduce a UDA annotation on the function 
to indicate the conversion can happen.

N3.5) can this be done in library code as opposed to compiler? 
that might work for non templated functions but what about 
templates? That seems more complicated isn't it?

Please let me know what you think.
Feb 01 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 1 February 2013 at 09:25:57 UTC, timotheecour wrote:
 Please let me know what you think.
Calling function is complicated enough, see property discussion for informations about this. As of the proposal in itself, out parameter is known to be confusing. They are here simply for C compat, and because D is unable to return multiple values. Fixing that problem is probably way then introducing something that promote out parameter usage.
Feb 02 2013
parent "timotheecour" <thelastmammoth gmail.com> writes:
 As of the proposal in itself, out parameter is known to be 
 confusing. They are here simply for C compat, and because D is 
 unable to return multiple values. Fixing that problem is 
 probably way then introducing something that promote out 
 parameter usage.
D can return tuples, and certainly its support could be improved (see [Issue 6365] AutoTupleDeclaration ), but this is besides the question. Oftentimes we NEED both versions, as I discussed in the previous post. The void fun(A a, ref B b) can reuse already allocated data, avoiding expensive allocations. This pattern is quite common. ---- void fun(int n, ref B b){ b.length=n; //do something with b } B fun(int n){ B b; fun(n,b); return b; } ----
Feb 02 2013