Thread overview
Lazy template arguments?
Jan 05, 2013
bearophile
Jan 13, 2013
comco
Jan 13, 2013
monarch_dodra
Jan 13, 2013
comco
Jan 13, 2013
bearophile
Jan 13, 2013
bearophile
January 05, 2013
In some case I'd like a hypothetical static ternary operator usable on types:

alias T = (U.sizeof <= 16) ?? ushort : size_t;

That is equivalent to:

static if (U.sizeof <= 16) {
    alias T = ushort;
} else {
    alias T = size_t;
}


The syntax of a possible library implementation is acceptable:

alias T = Ternary!(U.sizeof <= 16, ushort, size_t);


But I think to implement it well in library code you need a kind of "lazy" for types (it means the T2 type is not computed if b is false):


template Ternary(bool b, T1, lazy T2) {
    static if (b)
        alias Ternary = T1;
    else
        alias Ternary = T2;
}


Are such lazy type arguments generally useful for other purposes?

Bye,
bearophile
January 13, 2013
On Saturday, 5 January 2013 at 10:37:31 UTC, bearophile wrote:
> In some case I'd like a hypothetical static ternary operator usable on types:
>
> alias T = (U.sizeof <= 16) ?? ushort : size_t;
>
> That is equivalent to:
>
> static if (U.sizeof <= 16) {
>     alias T = ushort;
> } else {
>     alias T = size_t;
> }
>
>
> The syntax of a possible library implementation is acceptable:
>
> alias T = Ternary!(U.sizeof <= 16, ushort, size_t);
>
>
> But I think to implement it well in library code you need a kind of "lazy" for types (it means the T2 type is not computed if b is false):
>
>
> template Ternary(bool b, T1, lazy T2) {
>     static if (b)
>         alias Ternary = T1;
>     else
>         alias Ternary = T2;
> }
>
>
> Are such lazy type arguments generally useful for other purposes?
>
> Bye,
> bearophile

Isn't the whole ct metaprogramming with types kind of functional and immutable? So there is no perceivable difference between the results using different evaluation strategies? I thought that the template instantiation is already implemented as being lazy?
January 13, 2013
On Sunday, 13 January 2013 at 11:15:03 UTC, comco wrote:
> On Saturday, 5 January 2013 at 10:37:31 UTC, bearophile wrote:
>> In some case I'd like a hypothetical static ternary operator usable on types:
>>
>> alias T = (U.sizeof <= 16) ?? ushort : size_t;
>>
>> That is equivalent to:
>>
>> static if (U.sizeof <= 16) {
>>    alias T = ushort;
>> } else {
>>    alias T = size_t;
>> }
>>
>>
>> The syntax of a possible library implementation is acceptable:
>>
>> alias T = Ternary!(U.sizeof <= 16, ushort, size_t);
>>
>>
>> But I think to implement it well in library code you need a kind of "lazy" for types (it means the T2 type is not computed if b is false):
>>
>>
>> template Ternary(bool b, T1, lazy T2) {
>>    static if (b)
>>        alias Ternary = T1;
>>    else
>>        alias Ternary = T2;
>> }
>>
>>
>> Are such lazy type arguments generally useful for other purposes?
>>
>> Bye,
>> bearophile
>
> Isn't the whole ct metaprogramming with types kind of functional and immutable? So there is no perceivable difference between the results using different evaluation strategies? I thought that the template instantiation is already implemented as being lazy?

It's lazy in terms of instantiation, not in terms of evaluation of args. For example, if you write:

//----
lias T = Ternary!(U.sizeof <= 16, Foo!A, Foo!B);
//----

Then the compiler *will* instantiate Foo!B.

Bearophile: Is this proposal a pure optimization trick, or is there some functionality gains here. The only one I can think of, is if "Foo!B" would fail to compile. Is this what you are going for...?

Also:
//----
template Ternary(bool b, T1, lazy T2) {
//----
While is only T2 lazy?
January 13, 2013
comco:

> Isn't the whole ct metaprogramming with types kind of functional and immutable?

The answer is probably positive, but functional and lazy aren't exactly the same thing, from a computational point of view.


> I thought that the template instantiation is already
> implemented as being lazy?

I don't know how much.

Bye,
bearophile
January 13, 2013
On Sunday, 13 January 2013 at 11:26:57 UTC, monarch_dodra wrote:
> Bearophile: Is this proposal a pure optimization trick, or is there some functionality gains here. The only one I can think of, is if "Foo!B" would fail to compile. Is this what you are going for...?
>
> Also:
> //----
> template Ternary(bool b, T1, lazy T2) {
> //----
> While is only T2 lazy?

That was my point - and I thought that the arguments are evaluated lazily. Now, _if_ such support is added, why should we be able to pick the evaluation strategy - just make all the template arguments lazy by default - the behaviour won't change up for the most constructs, but it will be more expressive, because you'll be able to pass non-compiling arguments.
January 13, 2013
monarch_dodra:

> Is this proposal a pure optimization trick, or is there some functionality gains here. The only one I can think of, is if "Foo!B" would fail to compile. Is this what you are going for...?

It's first of all a way to implement a Ternary in library code, because in some situations instantiating a template causes an error, so the lazyness is needed to avoid those errors, and instantiate only the correct branch/argument. If this feature also reduces the compilation time a bit, then it's welcome :-)

Beside implementing a Ternary, do you see other usages for such lazy template arguments?


> Also:
> //----
> template Ternary(bool b, T1, lazy T2) {
> //----
> While is only T2 lazy?

My mistake, both of those arguments are better to be lazy:

template Ternary(bool b, lazy T1, lazy T2) {...}

Bye,
bearophile