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.
Andrei
While 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









deadalnix <deadalnix gmail.com> 