Template and Type Literals

Atila Neves atila.neves at gmail.com
Thu May 30 18:42:02 UTC 2024


On Tuesday, 21 May 2024 at 17:38:41 UTC, Quirin Schroll wrote:
> D has function and delegate literals (usually spelled `x => …` 
> or `(x) { … }` or `function (T x) {…}`). You know them, you 
> like them. I don’t have to explain to you how ugly `map`, 
> `filter` and other ranges would be to use if you had to define 
> and pass the function/predicate/… by name.
>
> What D lacks is something like that for constructs that aren’t 
> functions, in particular templates. The idea is that sometimes, 
> one wants to pass something to a template that isn’t a value, 
> e.g. a type or a template.
>
> A type literal is something like `struct { … }`, which you 
> could use as a template argument instead of a named struct. 
> Like with function literals, there are probably some 
> limitations (e.g. function literals can’t be recursive), 
> however, using `typeof(this)` allows one to refer to the 
> otherwise anonymous struct type, so from the top of my head, I 
> can’t think of one.
>
> More interesting are template literals. There can’t be proper 
> template literals, though, but specialized ones.
>
> What I mean by “proper template literals” is that there can’t 
> be `template(T) =>` because what’s going to be after the `=>` 
> arrow? Templates “return” by eponymous member, but the template 
> has no name.
>
> Example:
> ```d
> import std.meta;
>
> Instantiate!(alias T => const(T), int)[] xs = [ staticMap!(enum 
> T => T.sizeof, byte, short, int, long, struct{ long x, y; }) ];
> // const(int)[] xs = [1, 2, 4, 8, 16];
> ```
> For everything D has an abbreviated template syntax, there 
> should be a template lambda syntax using the same keyword, i.e. 
> `struct (T) { … }`, `class (T) { … }`, etc.
> For aggregates, parentheses around a single type parameter are 
> obligatory, but for `alias` and `enum`, they should be optional.
>
> Passing a type or template literal is equivalent to passing the 
> name of a newly defined aggregate type or template.
>
> I intend to limit those constructs to be template arguments 
> only. If you find use-cases, let me know, but I feel like 
> allowing them anywhere else makes things a lot more complicated.
>
> Grammar:
> ```diff
>     TemplateArgument:
>         Type
>         AssignExpression
>         Symbol
> +       AggregateLiteral
> +       TemplateLiteral
> +
> +   AggregateLiteral:
> +       struct { AggregateBody }
> +       union { AggregateBody }
> +       class { AggregateBody }
> +       interface { AggregateBody }
> +
> +   TemplateLiteral:
> +       alias TemplateParameters => TemplateArgument
> +       alias Identifier => TemplateArgument
> +       enum TemplateParameters => TemplateArgument
> +       enum Identifier => TemplateArgument
> +       struct TemplateParameters { AggregateBody }
> +       union TemplateParameters { AggregateBody }
> +       class TemplateParameters { AggregateBody }
> +       interface TemplateParameters { AggregateBody }
> ```
>
> Normally, after `TemplateParameters`, there is an optional 
> `Constraint`, but that doesn’t really make sense here.

I've wanted "metafunction lambdas" for a while now, as well as 
fixing the historical mistake we made with eponymous templates. 
What mistake, I hear you ask? Well, here's something we fixed wrt 
C++:

     ```
     struct Foo {
          Foo() { /* ... */ }
         ~Foo() { /* ... */ }
     };
     ```

Java inherited the same mistake, namely that we have to repeat 
the type's name to declare constructor(s) and the destructor. 
This makes refactoring harder, which is a Bad Thing(tm). In D we 
use `this` and Bob's your proverbial uncle.

Unfortunately, we then went and did something nearly exactly the 
same with templates that's caused me hours of debugging when I 
decide to rename the thing and don't immediately catch it because 
of reflection or `__traits(compiles)`.

Anyway, all to say that I've long wanted to write template 
lambdas and use `this` instead of a template's name.




More information about the dip.ideas mailing list