digitalmars.D - Structural Function Attributes
- Q. Schroll (63/63) Jun 06 2016 I'm pretty sure, someone before me has thought about that. Take
I'm pretty sure, someone before me has thought about that. Take pure as an example, but you can replace it by any subset of pure, nothrow, safe and nogc. Main reason: Assume a struct with simple opApply struct R { // pure -> error: dg possibly impure int opApply(scope int delegate(size_t i, ref int x) dg) { ... } } which does only pure operations modulo calls of dg. Then, opApply is pure if dg is pure. Further assume a function using that opApply int wannaBePure(R r) // pure -> error: R.opApply possibly impure { int s = 0; foreach (i, x; r) s += i*x; return s; } PROBLEM 1: Nobody wants to supply all possible combinations of attributes the delegate can have. Worse, if the struct R is a template, it is nearly impossible for e.g. nogc. -> Use a template opApply to infer attributes. PROBLEM 2: Specific to opApply, you cannot infer the foreach types if opApply is a template; even a trivial one or opApply(DG : int delegate(size_t, ref int))(scope DG dg) does not do this. -> Template is an improper solution. PROBLEM 3: Templates cannot be virtual. -> Template is not a solution at all. PROPOSED SOLUTION: For each (strong) attribute like pure, support a (weak) structural one, meaning that the function is pure if the parameters are. PLUS: Always infer structural attributes for functions with delegate/function parameters, but let the explicit notion be possible, as the programmer could want to guarantee structural pureness, cf. attribute inference on function templates can be denoted explicitly. FUN FACT: The structural attribute is actually not that weak. It makes (maybe many) functions pure, that wouldn't be otherwise. Back to the example: struct R { struct(pure) // dg pure -> opApply pure int opApply(scope int delegate(size_t i, ref int x) dg) { ... } } int wannaBePure(R r) pure // pure opApply -> pure { int s = 0; foreach (i, x; r) s += i*x; // pure stuff -> pure delegate -> pure opApply return s; } From what I see, struct(pure) is perfectly sound with inheriting and overwriting. To the overloading set, it can be seen as supplying both versions. As the code is not affected (only optimizing), this should be easy to handle in object code. The function has to be marked as sturct(whatever). The function must be compiled as it wouldn't have the attribute. Outside, it can be decided at compile-time. Ideas?
Jun 06 2016