Implementing tail-const in D

H. S. Teoh hsteoh at quickfur.ath.cx
Thu Jan 25 19:54:55 UTC 2018


On Tue, Jan 23, 2018 at 09:36:03AM +0000, Simen Kjærås via Digitalmars-d wrote:
[...]
> struct R(T) {
>     T[] arr;
>     auto opHeadMutable(this This)() {
>         import std.traits : CopyTypeQualifiers;
>         return R!(CopyTypeQualifiers!(This, T))(arr);
>     }
> }
> 
> This is the code you will need to write to ensure your types can be
> converted to head-mutable. opHeadMutable provides both a method for
> conversion, and a way for the HeadMutable!T template to extract the
> correct type.

I like this idea quite much, actually, in spite of the lack of support
for implicit conversions, which is a loss (but as you said, we can't
support that without breaking a lot of existing stuff or introducing
massive changes that are unlikely to be accepted by Walter & Andrei).
Basically, instead of a bunch of convoluted rules with poorly-understood
corner cases, we delegate the responsibility of constructing a head
mutable type to the type itself, so the user code decides for itself how
to construct such a thing. It's a clever idea.

In fact, if the standard implementation of opHeadMutable is basically
the same across all types (or most types), it could even be provided as
a mixin template in the library, then all you have to do is to `mixin
headMutable` or something along those lines, and off you go.


> The actual implementation of HeadMutable!T and headMutable is
> available here:
> https://gist.github.com/Biotronic/67bebfe97f17e73cc610d9bcd119adfb
> 
> 
> My current issues with this:
> 1) I don't like the names much. I called them Decay, decay and opDecay
> for a while. Name suggestions are welcome.

I'll leave the bikeshedding to others. :-P


> 2) As mentioned above, implicit conversions would be nice, but that'd
> require an entirely new type of implicit conversion in addition to
> alias this, opDispatch, opDot and interfaces/base classes. This would
> require some pretty darn good reasons, and I don't think a call to
> headMutable() is that much of a problem.

In fact, if done correctly, I think the *lack* of implicit conversion
might actually be a good thing, because the code will be more
self-documenting as to what its intent really is.

	const(MyRange!T) r = ...;
	...
	auto s = r.headMutable; // <-- explicit documentation of intent

as opposed to:

	const(MyRange!T) r = ...;
	...
	MyRange!(const T) s = r; // <-- intent not as clear

While one could argue the latter is more concise and therefore more
readable, the problem is that it hides the fact that user-defined code
is being executed to perform the implicit conversion, and since D allows
you to do all sorts of stuff with compile-time arguments, there's no
guarantee that the implicit call to r.headMutable actually does what you
think it does.  Having to call .headMutable explicitly makes it clear
that user code is being invoked, so that there is no illusion that we're
just "automatically" promoting const(Templ!T) to Templ!(const T).


> Questions:
> Is a DIP required for this? Should I create a PR implementing this for
> the range types in Phobos? What other types would benefit from this?
[...]

Since this would be introducing new symbols to Phobos, as well as,
arguably, a new paradigm (or a significant extension to the existing
paradigms), I think it would be best to get Andrei's attention on this
issue and persuade him to support this, before submitting any PRs, lest
the PR gets stuck in the queue over nitpicks and rot forever.

For one thing, I'm in favor of something in this general direction (even
if it doesn't end up being this specific proposal), so that we can use
const more pervasively than right now, because currently, the
transitivity of const severely limits how much code can actually use it.
As Jonathan David has said, many of us have pretty much given up on
const because it's just too difficult to work with.  Having standard
library support for .headMutable is an important first step in making
const more widely usable, so that more code can benefit from its
guarantees.


T

-- 
Talk is cheap. Whining is actually free. -- Lars Wirzenius


More information about the Digitalmars-d mailing list