How templates work (bonus) - Full instantiation of Iota!(1,5)

Simen Kjærås simen.kjaras at gmail.com
Thu Jun 4 12:34:14 UTC 2020


On Thursday, 4 June 2020 at 12:08:58 UTC, Stefan Koch wrote:
> On Thursday, 4 June 2020 at 12:03:00 UTC, Simen Kjærås wrote:
>> On Thursday, 4 June 2020 at 11:33:48 UTC, Stefan Koch wrote:
>>> [...]
>>
>> The way you're doing it seems to change about halfway (notice 
>> the sudden change in slope in the indentation at Seq!(3, 
>> ...)), and it's not really proper D in any case, but there's a 
>> few missing exclamation marks (after Iota in Seq!(2, Iota(2 + 
>> 1, 5)), and after the final Seq in }.Seq => (3, Seq!(4, 
>> Seq())))). There's also a spurious set of parentheses in }.Seq 
>> => (2, (Seq!(3, Seq!(4, Seq!())))).

More:
This line is missing a trailing parenthesis:
     }.Iota => (3, Seq!(4, Seq!())
This line has an extra trailing parenthesis:
     }.Seq => (3, Seq!(4, Seq())))
This line has an extra trailing parenthesis:
     }.Seq => (1, Seq!(2, Seq!(3, Seq(4, Seq!())))))
This line is missing some starting parentheses (Seq!3 and Seq!4), 
and has an extra trailing one:
     }.Iota => (1, Seq!(2, Seq!3, Seq!4, Seq!()))))))

This line looks different from all the other expansions:
     { Seq!() => () }.Seq => ()
I assume it should be
     {
         alias Seq = ();
     }.Seq => ()

There's two instances of seq in lowercase (alias seq = Seq!(2, 
...) and alias seq = Seq!(4, ...)).


> The reason I show every step explicitly is because that's 
> what's the compiler has to do.
> I actually did omit a few steps. Such as finding the right 
> template declaration to use.
> Which requires you to go up the scopes you just created.

Good point. With that, it looks like this:

Iota!(1, 5):
{
     alias Iota = Seq!(1, Iota!(1 + 1, 5));
     Seq!(1, Iota!(1 + 1, 5)):
     {
         alias Seq = (1, Iota!(1 + 1, 5));
         Iota!(1 + 1, 5):
         {
             alias Iota = Seq!(2, Iota!(2 + 1, 5));
             Seq!(2, Iota!(2 + 1, 5)):
             {
                 alias Seq = (2, Iota!(2 + 1, 5));
                 Iota!(2 + 1, 5):
                 {
                     alias Iota = Seq!(3, Iota!(3 + 1, 5));
                     Seq!(2, Iota!(2 + 1, 5)):
                     {
                         alias Seq = (3, Iota!(3 + 1, 5));
                         Iota!(3 + 1, 5):
                         {
                             alias Iota = Seq!(4, Iota!(4 + 1, 5));
                             Seq!(4, Iota!(4 + 1, 5)):
                             {
                                 alias Seq = (4, Iota!(4 + 1, 5));
                                 Iota!(4 + 1, 5):
                                 {
                                     alias Iota = Seq!();
                                     Seq!():
                                     {
                                         alias Seq = ();
                                     }.Seq => ()
                                 }.Iota => ()
                             }.Seq => (4, ())
                         }.Iota => (4, ())
                     }.Seq => (3, (4, ()))
                 }.Iota => (3, (4, ()))
             }.Seq => (2, (3, (4, ())))
         }.Iota => (2, (3, (4, ())))
     }.Seq => (1, (2, (3, (4, ()))))
}.Iota => (1, (2, (3, (4, ()))))

An argument could certainly be made to include Seq!(...) in every 
list after =>, but when should I finally evaluate those, then? I 
opted for parenthesized groups instead.

--
   Simen


More information about the Digitalmars-d mailing list