Implementing tail-const in D
Simen Kjærås
simen.kjaras at gmail.com
Thu Jan 25 21:33:10 UTC 2018
On Thursday, 25 January 2018 at 19:54:55 UTC, H. S. Teoh wrote:
> 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).
Yeah. Arrays and pointers are special, and turn into their
head-mutable equivalents completely unbidden, when passed to
functions. No other types in the language does that, and it seems
a weird semantic to specify for a given type, especially if just
for making head-mutable work.
> 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.
Thank you. Given D's template system is very powerful, I think a
solution where the type couldn't define its own conversion
wouldn't be anywhere near viable.
> 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.
I believe this should be possible, but
https://issues.dlang.org/show_bug.cgi?id=11098 causes me
headaches:
mixin template headMut()
{
auto opHeadMutable(this This)()
{
import std.traits : CopyTypeQualifiers, TemplateArgsOf,
TemplateOf;
import std.meta : staticMap;
alias Tmpl = TemplateOf!This;
alias Args = TemplateArgsOf!This;
template Apply(T...)
{
static if (is(T[0]))
alias Apply =
HeadMutable!(CopyTypeQualifiers!(This, T));
else
alias Apply = T; // cannot use local '__lambda1'
as parameter
}
alias ReturnType = Tmpl!(staticMap!(Apply, Args));
return ReturnType(this);
}
}
Another thought: T.opHeadMutable() and the free function
headMutable() do basically the same thing, and could be unified
through UFCS. There'd be a free function headMutable() that works
for built-in types and UDTs that don't define their own
T.headMutable(), and then UDTs with T.headMutable() would Just
Work™. One less moving part.
>> 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.
My thoughts exactly, and the reason I haven't yet created a PR
for it.
> 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.
Thanks. I hope it can at least be a stepping stone on the way.
--
Simen
More information about the Digitalmars-d
mailing list