digitalmars.D - One more simple idea for simplifying constraints
- Andrei Alexandrescu (26/26) Apr 25 2016 Sometimes we use constraints to distinguish different approach to
- Stefan Koch (20/49) Apr 25 2016 While working on implementing template constraints for SDC.
- deadalnix (2/58) Apr 25 2016 It is not semantically equivalent.
- H. S. Teoh via Digitalmars-d (39/62) Apr 25 2016 [...]
Sometimes we use constraints to distinguish different approach to implementation, e.g. find for a string is different than find for forward ranges is different from find for input ranges etc. One simple idea here (which Walter also advised a while ago) is to push implementation details inside the, well, implementation, e.g.: Type functionName(TemplateArgs)(Args) if (HighLevelConstraint) { static if (LowLevelCapability1) { .. specialization 1 ... } else static if (LowLevelCapability1) { ... specialization 2 ... } else { .. conservative impl ... } } That way the user/documentation only deals with the high level constraint (the minimum necessary for the function to work). Inside, the function decides the exact approach. It's an obvious idea now but many times in the past I didn't pursue it. Andrei
Apr 25 2016
On Monday, 25 April 2016 at 18:50:28 UTC, Andrei Alexandrescu wrote:Sometimes we use constraints to distinguish different approach to implementation, e.g. find for a string is different than find for forward ranges is different from find for input ranges etc. One simple idea here (which Walter also advised a while ago) is to push implementation details inside the, well, implementation, e.g.: Type functionName(TemplateArgs)(Args) if (HighLevelConstraint) { static if (LowLevelCapability1) { .. specialization 1 ... } else static if (LowLevelCapability1) { ... specialization 2 ... } else { .. conservative impl ... } } That way the user/documentation only deals with the high level constraint (the minimum necessary for the function to work). Inside, the function decides the exact approach. It's an obvious idea now but many times in the past I didn't pursue it. AndreiWhile working on implementing template constraints for SDC. I had a similar idea, basically a template constraint can be rewritten as a static if inside the template. R Tmpl (U) (U u) if (is(U == int)) { pragma(msg, "U is an int"); } R Tmpl (U) (U u) if (is(U == string)) { pragma(msg, "U is a string"); } is equivalent to R Templ (U u) { static if (is(U == int)) { pragma(msg, "U is an int"); } else static if (is(U == string)) { pragma(msg, "U is a string"); } else static assert(0, "Can only be instantiated with int or string"); } Except that you just get one error message instead of 2 overloads displayed.
Apr 25 2016
On Tuesday, 26 April 2016 at 03:17:09 UTC, Stefan Koch wrote:On Monday, 25 April 2016 at 18:50:28 UTC, Andrei Alexandrescu wrote:It is not semantically equivalent.Sometimes we use constraints to distinguish different approach to implementation, e.g. find for a string is different than find for forward ranges is different from find for input ranges etc. One simple idea here (which Walter also advised a while ago) is to push implementation details inside the, well, implementation, e.g.: Type functionName(TemplateArgs)(Args) if (HighLevelConstraint) { static if (LowLevelCapability1) { .. specialization 1 ... } else static if (LowLevelCapability1) { ... specialization 2 ... } else { .. conservative impl ... } } That way the user/documentation only deals with the high level constraint (the minimum necessary for the function to work). Inside, the function decides the exact approach. It's an obvious idea now but many times in the past I didn't pursue it. AndreiWhile working on implementing template constraints for SDC. I had a similar idea, basically a template constraint can be rewritten as a static if inside the template. R Tmpl (U) (U u) if (is(U == int)) { pragma(msg, "U is an int"); } R Tmpl (U) (U u) if (is(U == string)) { pragma(msg, "U is a string"); } is equivalent to R Templ (U u) { static if (is(U == int)) { pragma(msg, "U is an int"); } else static if (is(U == string)) { pragma(msg, "U is a string"); } else static assert(0, "Can only be instantiated with int or string"); } Except that you just get one error message instead of 2 overloads displayed.
Apr 25 2016
On Mon, Apr 25, 2016 at 02:50:28PM -0400, Andrei Alexandrescu via Digitalmars-d wrote:Sometimes we use constraints to distinguish different approach to implementation, e.g. find for a string is different than find for forward ranges is different from find for input ranges etc. One simple idea here (which Walter also advised a while ago) is to push implementation details inside the, well, implementation, e.g.: Type functionName(TemplateArgs)(Args) if (HighLevelConstraint) { static if (LowLevelCapability1) { .. specialization 1 ... } else static if (LowLevelCapability1) { ... specialization 2 ... } else { .. conservative impl ... } }[...] This can also be written: template functionName(TemplateArgs) if (HighLevelConstraint) { static if (...) Type functionName(Args) { // specialization 1 } else static if (...) Type functionName(Args) { // specialization 2 } else Type functionName(Args) { // conservative impl } } This form might be preferable if there's some common code between different specializations that can be factored out of the static if (but inside the template body). Many of the overloads in Phobos arguably should be written in this way, because they aren't really overloads in the traditional sense of using the same logical name for multiple combinations of arguments, but are more like template specializations, i.e., same name with same logical combination of arguments, but possibly different argument types. E.g., find() with certain string types have specialized implementations, but from the user's POV find(string s) really should be considered a single overload, not multiple overloads differing (in terms of API) only in sig constraints. Consolidating specializations this way will not only allow better error messages, but will also make the code easier to maintain. I have advocated for this approach in the past, but the idea was basically shot down. Hopefully this time round people will see its merits. T -- Life is too short to run proprietary software. -- Bdale Garbee
Apr 25 2016