November 27, 2019
On 11/27/19 11:15 AM, Steven Schveighoffer wrote:
> What I am proposing is that you can mark items as @temporary or something like that, and those templates will be reevaluated each time. And in the case of something like hasFoo, I'd argue it's just a thin wrapper over a __traits call, so it probably should be reevaluated each time.

Think of it like "weak pure". In strong pure functions, the result is always the same, because the data passed in is always the same. But weak pure functions can be used inside those functions even though their parameters and results can be mutable. It allows for much more pleasant experience.

It allows one to have the public template as "this is final, once it's evaluated, store it and it's always the same." But the innards, which can be hairy, complex, horribly performing and used only once (or maybe a couple times), can be left to the GC, because once the head is finalized, they won't be instantiated with those parameters again.

The more I think about it, the more I like the CTFE with Types as first class approach, because then I can use actual mutating code vs. immutable functional approach that is required with templates.

-Steve
November 27, 2019
On Wed, Nov 27, 2019 at 11:32:13AM -0500, Steven Schveighoffer via Digitalmars-d wrote: [...]
> The more I think about it, the more I like the CTFE with Types as first class approach, because then I can use actual mutating code vs. immutable functional approach that is required with templates.
[...]

I've been following this thread, and am coming to the same conclusion too.

While templates are expressive enough to encode complex computations, they aren't exactly the most conducive to such, and in terms of code gen they aren't really the best tool for the job. Strictly speaking templates really should be about manipulating the AST; using them to perform computations is possible but a poor choice of tool IMO.

CTFE with first class types is much better because then it becomes obvious that this is for *computation*, and the compiler knows that it's intended to be computation rather than AST manipulation, so it can optimize accordingly (discard intermediate results, etc.). No need for additional annotations on templates or other such additional complexities.

And since we can already use CTFE results in template arguments, this is not a loss to expressiveness. We just re-encode what we currently use templates for into CTFE form, let the CTFE engine perform whatever arbitrary computations we want on it, then return the result as a template argument list that can be used to transform the AST as previously intended.

We then have the nice paradigm:

	Computations -> CTFE
	AST transformations -> templates

and we can get rid of ugly recursive templates like staticMap, and replace it with a much nicer CTFE implementation, or even outright just drop staticMap and replace it with std.algorithm.map taking an alias list as argument, thus staying DRY.


T

-- 
Recently, our IT department hired a bug-fix engineer. He used to work for Volkswagen.
November 27, 2019
On Wednesday, 27 November 2019 at 16:32:13 UTC, Steven Schveighoffer wrote:
> On 11/27/19 11:15 AM, Steven Schveighoffer wrote:
>
> The more I think about it, the more I like the CTFE with Types as first class approach, because then I can use actual mutating code vs. immutable functional approach that is required with templates.
>
> -Steve

Yes that is the point.
first class types during ctfe allows you to use weak purity instead of strong purity!
And therefore makes AST manipulation or introspection much more efficient!

I'll build a tiny POC shortly. The thing that I got stuck with last time was the lexer/parser modification that is required to flag type arguments to ctfe functions.
December 01, 2019
On Wednesday, 27 November 2019 at 18:11:37 UTC, H. S. Teoh wrote:
> On Wed, Nov 27, 2019 at 11:32:13AM -0500, Steven Schveighoffer via Digitalmars-d wrote: [...]
>> [...]
> [...]
>
> I've been following this thread, and am coming to the same conclusion too.
>
> While templates are expressive enough to encode complex computations, they aren't exactly the most conducive to such, and in terms of code gen they aren't really the best tool for the job. Strictly speaking templates really should be about manipulating the AST; using them to perform computations is possible but a poor choice of tool IMO.
>
> CTFE with first class types is much better because then it becomes obvious that this is for *computation*, and the compiler knows that it's intended to be computation rather than AST manipulation, so it can optimize accordingly (discard intermediate results, etc.). No need for additional annotations on templates or other such additional complexities.
>
> And since we can already use CTFE results in template arguments, this is not a loss to expressiveness. We just re-encode what we currently use templates for into CTFE form, let the CTFE engine perform whatever arbitrary computations we want on it, then return the result as a template argument list that can be used to transform the AST as previously intended.
>
> We then have the nice paradigm:
>
> 	Computations -> CTFE
> 	AST transformations -> templates
>
> and we can get rid of ugly recursive templates like staticMap, and replace it with a much nicer CTFE implementation, or even outright just drop staticMap and replace it with std.algorithm.map taking an alias list as argument, thus staying DRY.
>
>
> T

Perhaps this is the opportunity to make a good runtime reflection system. We have typeid() for types, for an alias sequence which contains only types an no declarations we can implement NoDuplicates as a function that takes a TypeInfo[] and return the array with no duplicates in it, but we need a way to get a compile-time type from a TypeInfo, sort of a reversed typeid().
December 01, 2019
On Wednesday, 27 November 2019 at 20:02:52 UTC, Stefan Koch wrote:
> On Wednesday, 27 November 2019 at 16:32:13 UTC, Steven Schveighoffer wrote:
>> On 11/27/19 11:15 AM, Steven Schveighoffer wrote:
>>
>> The more I think about it, the more I like the CTFE with Types as first class approach, because then I can use actual mutating code vs. immutable functional approach that is required with templates.
>>
>> -Steve
>
> Yes that is the point.
> first class types during ctfe allows you to use weak purity instead of strong purity!
> And therefore makes AST manipulation or introspection much more efficient!
>
> I'll build a tiny POC shortly. The thing that I got stuck with last time was the lexer/parser modification that is required to flag type arguments to ctfe functions.

The problem with going the path of giving super powers to CTFE functions is that it creates a division between runtime and CTFE then we will get functions which only work in CTFE which may or may not be a good thing.
December 01, 2019
On 12/1/19 4:04 PM, Suleyman wrote:
> Perhaps this is the opportunity to make a good runtime reflection system. We have typeid() for types, for an alias sequence which contains only types an no declarations we can implement NoDuplicates as a function that takes a TypeInfo[] and return the array with no duplicates in it, but we need a way to get a compile-time type from a TypeInfo, sort of a reversed typeid()
I actually figured out a Type-only mechanism to CTFE a NoDuplicates list. Translate each type into a string name, then no-dup the string array, creating a string of AliasSeq references, then mixin the result.

But having CTFE actually give me the types to translate back into an AliasSeq list would be so much better.

-Steve
December 01, 2019
On 12/1/19 4:14 PM, Suleyman wrote:
> On Wednesday, 27 November 2019 at 20:02:52 UTC, Stefan Koch wrote:
>> On Wednesday, 27 November 2019 at 16:32:13 UTC, Steven Schveighoffer wrote:
>>> On 11/27/19 11:15 AM, Steven Schveighoffer wrote:
>>>
>>> The more I think about it, the more I like the CTFE with Types as first class approach, because then I can use actual mutating code vs. immutable functional approach that is required with templates.
>>>
>>> -Steve
>>
>> Yes that is the point.
>> first class types during ctfe allows you to use weak purity instead of strong purity!
>> And therefore makes AST manipulation or introspection much more efficient!
>>
>> I'll build a tiny POC shortly. The thing that I got stuck with last time was the lexer/parser modification that is required to flag type arguments to ctfe functions.
> 
> The problem with going the path of giving super powers to CTFE functions is that it creates a division between runtime and CTFE then we will get functions which only work in CTFE which may or may not be a good thing.

We already have CTFE-only functions (assert(__ctfe)) Sometimes CTFE is far preferable to using template expansion.

-Steve
December 02, 2019
On Monday, 2 December 2019 at 01:10:26 UTC, Steven Schveighoffer wrote:
> On 12/1/19 4:04 PM, Suleyman wrote:
>> Perhaps this is the opportunity to make a good runtime reflection system. We have typeid() for types, for an alias sequence which contains only types an no declarations we can implement NoDuplicates as a function that takes a TypeInfo[] and return the array with no duplicates in it, but we need a way to get a compile-time type from a TypeInfo, sort of a reversed typeid()
> I actually figured out a Type-only mechanism to CTFE a NoDuplicates list. Translate each type into a string name, then no-dup the string array, creating a string of AliasSeq references, then mixin the result.
>
> But having CTFE actually give me the types to translate back into an AliasSeq list would be so much better.
>
> -Steve

It can work with some declarations I don't to what extend though since __traits(isSame) does a range of comparisons depending on the arguments. But string manipulation with CTFE is not cheap either. Here is a challenge for you, try to make a string with CTFE that has 1 million times the word int separated by a comma like "int, int, int, ..." in under 4GB of memory use if you can go below 4GB then lower the bar from there to 1.5GB.

December 02, 2019
On Monday, 2 December 2019 at 01:11:57 UTC, Steven Schveighoffer wrote:
> On 12/1/19 4:14 PM, Suleyman wrote:
>> On Wednesday, 27 November 2019 at 20:02:52 UTC, Stefan Koch wrote:
>>> On Wednesday, 27 November 2019 at 16:32:13 UTC, Steven Schveighoffer wrote:
>>>> On 11/27/19 11:15 AM, Steven Schveighoffer wrote:
>>>>
>>>> The more I think about it, the more I like the CTFE with Types as first class approach, because then I can use actual mutating code vs. immutable functional approach that is required with templates.
>>>>
>>>> -Steve
>>>
>>> Yes that is the point.
>>> first class types during ctfe allows you to use weak purity instead of strong purity!
>>> And therefore makes AST manipulation or introspection much more efficient!
>>>
>>> I'll build a tiny POC shortly. The thing that I got stuck with last time was the lexer/parser modification that is required to flag type arguments to ctfe functions.
>> 
>> The problem with going the path of giving super powers to CTFE functions is that it creates a division between runtime and CTFE then we will get functions which only work in CTFE which may or may not be a good thing.
>
> We already have CTFE-only functions (assert(__ctfe)) Sometimes CTFE is far preferable to using template expansion.
>
> -Steve

Not to this extent though. What we're potentially discussing here is functions which have a reusable body like a runnable template. For example a CTFE function `bool isSame(alias A, alias B) { return __traits(isSame, A, B); }` this is unlike any regular function that we have today.
December 02, 2019
On Monday, 2 December 2019 at 02:02:04 UTC, Suleyman wrote:
>
> Not to this extent though. What we're potentially discussing here is functions which have a reusable body like a runnable template. For example a CTFE function `bool isSame(alias A, alias B) { return __traits(isSame, A, B); }` this is unlike any regular function that we have today.

Interesting this is exactly the syntax I wanted to use ;)

Any ctfe function that has an alias parameter is a ctfe only function.
Using this you can give a function a default alias parameter if you want it to be compile time only.

it's a simple rule, and not confusing at all.