Just sayin', fwiw...
H. S. Teoh
hsteoh at quickfur.ath.cx
Thu May 16 17:47:26 UTC 2019
On Thu, May 16, 2019 at 02:39:40PM +0000, FeepingCreature via Digitalmars-d wrote:
> On Thursday, 16 May 2019 at 03:11:15 UTC, Nick Sabalausky (Abscissa) wrote:
> > Not to beat anyone over the head or push for any change (I know not
> > to do that 'round these parts these days ;) )...but I've noticed a
> > very frequent pattern in my own usage of D:
> >
> > 1. I write a bunch of code.
> > 2. I take advantage of ranges and std.algorithm and think I'm being
> > all hip and cool and awesome.
> > 3. I hit compile.
> > 4. Something in std.algorithm fails to find a matching overload.
> ...
> > 10. I toss in ".byCodeUnit", it works, I go about the rest of my
> > day.
> >
> > And I'm a D veteran. I've been using D since before v1.0 (yes,
> > pre-D1). I can't even imagine how painful this would be for a D
> > newcomer.
[...]
> This is not a problem with string autodecoding, this is a problem with
> the utterly atrocious error reporting where if the compiler fails to
> find an overload match due to template constraints, it gives you
> precisely zero indication what the actual root cause is.
Inscrutable error messages involving unreadable sig constraints are only
a symptom.
The REAL problem as Walter has pointed out elsewhere is that Phobos uses
far too much function overloading. I'd say Phobos abuses function
overloading. There are far too many overloads that ought *not* to be
overloads, but should be merged into a single, logical function with
various cases differentiated by static ifs inside the function body,
with a static assert at the end explaining the problem should none of
the cases match.
Function overloads should be used where there is a LOGICAL distinction
in the public-facing API, e.g.:
auto find(R,E)(R haystack, E needle)
vs.
auto find(alias pred, R)(R haystack)
They are logically distinct because one overload takes the object being
searched as an argument, whereas the other takes a predicate to
evaluate.
But where the distinction is in implementation details, such as:
auto find(R,E)(R haystack, E needle) if (isSomeString!R)
auto find(R,E)(R haystack, E needle) if (!isSomeString!R)
then they really should NOT be overloads, but should instead be a SINGLE
logical function with the implementation details hidden inside the
function body:
auto find(R,E)(R haystack, E needle)
{
static if (isSomeString!R)
... // implementation #1
else // !isSomeString!R)
... // implementation #2
}
Why should the user care that find's implementation treats strings and
non-string separately? That's an irrelevant implementation detail that
should be hidden inside the function body. Exposing it as a sig
constraint in a public-facing API breaks encapsulation, and is an
anti-pattern.
I've already repeated this many, many times, but there still remains a
lot of Phobos/druntime code written according to this anti-pattern,
including a recent example of hashOf being a *21*-function overload set
in druntime. Insane!! Glancing through those overloads reveals that
the sig constraints are all implementation details, i.e., they should
NOT be sig constraints in a public-facing API, but static if conditions
inside the function body dispatching to various different
implementations.
Abusing overload sets for this purpose is an anti-pattern, and needs to
stop.
T
--
If Java had true garbage collection, most programs would delete themselves upon execution. -- Robert Sewell
More information about the Digitalmars-d
mailing list