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