I've just fixed UFCS for the experimental type function branch

Paul Backus 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 
in D.)

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 mailing list