digitalmars.D - Ouput-UFCS proposal: void fun(A a,ref B b) <=> B fun(A a);
- timotheecour (61/61) Feb 01 2013 I'd like to suggest the following feature that extends UFCS to
- deadalnix (7/8) Feb 02 2013 Calling function is complicated enough, see @property discussion
- timotheecour (18/23) Feb 02 2013 D can return tuples, and certainly its support could be improved
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
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
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