On 11/02/2015 9:00 p.m., Jakob Ovrum wrote:
------------
Preface
------------

I'd like to start by saying that this is a relatively low-impact
enhancement in the short term, but should pay off in the long term. It
also requires very little effort, so it is low-hanging fruit, although
it requires some foresight to see the benefit.

------------
Primer of type concepts for the uninitiated (skip if you know this stuff)
------------

In D we have the idea of a type concept. Current notable concepts are
the range concept and the container concept. The idea is that any type
that satisfies the operations of a certain usage pattern can be said to
satisfy a certain type concept, and thus be usable in algorithms that
use a permutation of said usage pattern. The operations making up a type
concept are called the primitives of the concept.

For example, for a type to satisfy the input range concept, the
following usage pattern must compile:
---
R r;              // can define a range object
if (r.empty) {}   // can test for empty
r.popFront();     // can invoke popFront()
auto h = r.front; // can get the front of the range of non-void type
---
The three required operations for the input range concept are the front,
empty and popFront primitives. In addition there may be certain
restrictions on runtime behaviour; for example, `front` should never be
called on an empty range.

For convenient verification of a type satisfying a concept, we have
concept checker templates such as isInputRange[1].

------------
Suggestion
------------

Lately there is a trend of splitting up modules into packages in Phobos.
Notably, std.range and std.container have been split up into packages.

Currently all the range concept checkers are defined in a module
std.range.primitives, bundled with the UFCS implementations of the range
primitives for in-built slice types.

Containers do not (yet) have concept checkers, but I consider it likely
we'll see them in the future, as we see more generic container
algorithms as well as higher-order containers.

Additionally, Andrei has suggested a new type RefCountedSlice!T that
presents the same dynamic array interface of T[], but with a
reference-counted backend in lieu of the GC backend of T[]. It is
conceivable that generic array algorithms may want to accept either
type, and thus the "dynamic slice" concept is born.

Putting the complexity of the container concept aside; I think we should
factor out the concept checkers from std.range.primitives and put them
in std.range.concept and establish a convention of using modules named
std.*.concept for concept checkers in the future. The consistency gained
by such a convention makes type concepts easier to understand and
commonly used module names easier to remember. If we do it now, there is
no breakage, as the splitting of std.range has not yet been released:
hence the otherwise clumsy timing of this suggestion.

It is very little work, but anticipating complaints of bike-shedding if
I didn't explain myself, I decided to post here first. I'd like to get
some feedback before I file a PR.

[1] http://dlang.org/phobos/std_range#isInputRange

As long as the std.concept package get's good documentation, I think its a damn good idea!

Reply via email to