Why does D not have generics?

sighoya sighoya at gmail.com
Wed Jan 13 17:53:27 UTC 2021


On Monday, 11 January 2021 at 18:23:20 UTC, Q. Schroll wrote:
> The only programming language I know of that has both, 
> templates and generics, is C++/CLI and ones closely related.
>
> I wonder, why D has classes similar to C# and Java, but does 
> not have generics.

Because OOP could be rarely supported in D without OOP and pure 
template programming while templates already serve the need for 
generics excluding the complexity they are introducing.


> A generic class or interface states its requirements (base 
> classes, interfaces, [never seen in the wild:] subclasses, ...) 
> to its type parameters exactly.

D can already do that with where constraints.

> Everything that is part of the implementation is checked when 
> the generic aggregate is defined.

So simply speaking you seek for eagerly checked templates which 
indeed seems to be
  an advantage of generics but why not optionally the same for 
templates?

Rather reinventing the wheel, why not modulating the template 
error system to infer and uppropagate where constraints 
automatically by traversing type/function bodies?

Another issue of generics are the parametrized error messages 
often disliked by people using them.
We could do that, in theory, better just by mentioning the 
position of the occurred error in the template-expanded code 
fragment similar to how Python handles type errors.
It would remove the barrier of template utilization a lot.


> Generics allow for implicit conversion by covariance and 
> contravariance. (C# [1]) Generics allow for reducing an 
> interface to its covariant or contravariant part-interface 
> (that is a supertype of the interface, really). (Java [2, 3])

I don't see any reason why not providing them with templates, too 
with specialized syntax for example by:

//Covariance
dlist!(T where T:A || T:B) ==> dlist!(Algebraic!(A,B))

//Contravariance
dlist!(T where A:T) ==> dlist!(Object)//where compiler rejects 
any assignment of A's strict subtypes.

> Using templates, the compiler checks requirements only for 
> specific instances. It might be that the requirements are 
> insufficient, but because no test tried the potentially very 
> specific type argument, it will be unrecognized.

Yep, sorta implicit where constraints would serve the purpose 
here.

>
> Also, one feature D doesn't have, is expressing the precise 
> union or intersection of interfaces: Say you have two 
> interfaces I and J.

Isn't a question about templates rather about intersection and 
union types as language level concept or as library solution.

> The interface (I & J) has all the methods specified by any of 
> them. A class that implements I and J automatically implements 
> (I & J).
> The interface (I | J) has all the methods specified by both of 
> them. A class that implements I or implements J automatically 
> implements (I | J). If you e.g. iterate an (I | J)[] object, 
> you can call any method required by both interfaces. 
> (Typescript [4])
> It might be hard or even impossible to implement this using 
> vtables and stuff.
>
Personally, I think it can with kinda implicitCoercionOp and 
Algebraic and some Intersection like variant.

> In D, one can easily create templates intersectInterface(Is...) 
> and unionInterface(Is...) that basically do that.
>
> It could very well be that D doesn't have them because they 
> have to be implemented and maintained, and the cost/benefit 
> ratio wasn't good enough.

D has already Algebraic for Unions, don't know about Intersection 
implementations.

Note that the implementation for Unions vary. In Scala (and 
proposed for C#) they are purely class/interface based, i.e. the 
union of two classes is internally just the supertype of both 
classes and the intersection of interfaces are classes/interfaces 
implementing/extending all the said interfaces which could 
implemented with some support of compile time reflection for OOP 
hierarchies.
It has however the disadvantage of overloading ambiguities when 
two pairs of classes have the same supertype.

But I would prefer to support other types than classes and 
interfaces as well just as it is the case with Algebraic.



More information about the Digitalmars-d mailing list