I've just fixed UFCS for the experimental type function branch
snarwin at gmail.com
Fri Sep 11 11:54:20 UTC 2020
On Friday, 11 September 2020 at 02:24:07 UTC, H. S. Teoh wrote:
> On Fri, Sep 11, 2020 at 01:07:55AM +0000, Paul Backus via
> Digitalmars-d wrote: [...]
>> I think the main difficulty of scaling code bases the rely
>> heavily on templates (either D or C++), [...], is that
>> templates themselves--not the code they generate when you
>> instantiate them, but the actual *templates*--are essentially
>> dynamically typed. In general, there's no way to catch errors
>> in a template until you "run" it (that is, instantiate it) and
>> see what it does.
> This is why when I write template code, I try to write
> defensively in a way that makes as few assumptions as possible
> about the template arguments. Ideally, every operation you'd
> do with that type should be tested in the sig constraints.
> Even better would be if the compiler enforced this: unless you
> tested for some operation in the sig constraints, that
> operation would be deemed illegal. But in the past Walter &
> Andrei have shot down Concepts, which is very similar to this
> idea, so I don't know how likely this will ever make it into D.
Yeah, that's basically the traits/typeclasses approach: you
commit to a particular set of constraints, and the compiler
checks your generic code against them *prior* to instantiation
with any particular type (or "monomorphization," as the
Rustaceans call it).
The main downside is that you can't do design-by-introspection.
Once you commit to a typeclass, its interface is all you get. If
you want your algorithm to work differently for InputRange and
RandomAccessRange, you have to write two implementations. And if
you don't want to deal with the combinatorial blow-up, you just
use the least-restrictive typeclass possible, and miss out on any
opportunities for progressive enhancement.
(Hypothesis: one consequence of this is that an optimizing
compiler backend has to work harder, on average, to get efficient
code out of a Rust iterator than it does for the analogous range
Theoretically, if you had something like a type-level version of
TypeScript's flow-based type analysis, you could combine the two
approaches. But I don't know of any language that's actually
implemented such a feature.
More information about the Digitalmars-d