May 12, 2020
On Wednesday, 6 May 2020 at 11:58:36 UTC, Stefan Koch wrote:
> Hello Guys,
>
> After a bit of fiddling the following code (and only that because I need do partial evaluation of the semantic pass on the function body manually ...)
> Now works on the Talias branch
>
> string F(alias y)
> {
>     return y.stringof;
> }
> static assert(F!(ulong) == "ulong");
> static assert(F!(uint) == "uint");

The following now works:

string[] memberNames(alias T)
{
    string[] result;

    if (is(typeof(T.tupleof)))
    {
        auto memberTuple = T.tupleof; // needs to be auto because we can't parse "alias[]" yet.
//        result.length = memberTuple.length; // we don't yet exclude this expression from semantic

        // will not be unrolled :)
        foreach(i, f; memberTuple)
        {
//          result[i] = __traits(identifier, f); // because we couldn't set the length this wouldn't work
            result ~= __traits(identifier, f); // note how the identifier f does not result in "f" ... this is neat but I might have to go back on this.
        }
    }

    return result;
}

struct S
{
    int x;
    double y;
    float z;
}

pragma(msg, memberNames(S)); // output is ["x","y","z"]

Note that the bang is not needed.
Because in the end a type function is a regular function.
The call mechanism just works, as long as an implicit cast from any type to alias is provided.
May 12, 2020
On Tuesday, 12 May 2020 at 14:14:21 UTC, Stefan Koch wrote:
> are you sure that that is the case for alias declarations?
> For me
> alias a = "Foo";
> causes Error: basic type expected, not "Foo"
> Which is identical to how they behave in type functions;

Can this old design flaw be fixed? 'alias a = Alias!"Foo"' shouldn't be necessary. We should be able to alias directly everything that we can pass to an alias template parameter.


May 12, 2020
On Tuesday, 12 May 2020 at 14:41:52 UTC, Max Samukha wrote:
> On Tuesday, 12 May 2020 at 14:14:21 UTC, Stefan Koch wrote:
>> are you sure that that is the case for alias declarations?
>> For me
>> alias a = "Foo";
>> causes Error: basic type expected, not "Foo"
>> Which is identical to how they behave in type functions;
>
> Can this old design flaw be fixed? 'alias a = Alias!"Foo"' shouldn't be necessary. We should be able to alias directly everything that we can pass to an alias template parameter.

Which name does "Foo" have?
There is a good reason for separating Symbols and literals.
May 12, 2020
On 5/12/20 11:42 AM, Stefan Koch wrote:
> On Tuesday, 12 May 2020 at 14:41:52 UTC, Max Samukha wrote:
>> On Tuesday, 12 May 2020 at 14:14:21 UTC, Stefan Koch wrote:
>>> are you sure that that is the case for alias declarations?
>>> For me
>>> alias a = "Foo";
>>> causes Error: basic type expected, not "Foo"
>>> Which is identical to how they behave in type functions;
>>
>> Can this old design flaw be fixed? 'alias a = Alias!"Foo"' shouldn't be necessary. We should be able to alias directly everything that we can pass to an alias template parameter.
> 
> Which name does "Foo" have?

alias x = Alias!"Foo";

pragma(msg, __traits(identifier, x)); // `a`

This is the name the Alias template gives to its parameter.

> There is a good reason for separating Symbols and literals.

Whether or not you like it, you can alias literals to template parameters. If type functions cannot do this, we will be stuck with using templates for many things, and I can totally envision this pattern happening:

string foo(string[] symbolnames, alias dummy = __dummy)
{
   // do something with symbolnames, ignore dummy
}

to force a type function instead of using CTFE when you want to manipulate a compile-time list of strings.

It reminds me of what people would resort to for a static foreach over a tuple when all they wanted was the index (before static foreach existed).

-Steve
May 12, 2020
On Tuesday, 12 May 2020 at 16:12:42 UTC, Steven Schveighoffer wrote:

> to force a type function instead of using CTFE when you want to manipulate a compile-time list of strings.
>
> It reminds me of what people would resort to for a static foreach over a tuple when all they wanted was the index (before static foreach existed).
>
> -Steve

There is no essentially no difference between a type function and CTFE.
Type functions are really just passing type as expressions to CTFE.
Well that and the ability to assign to alias.
Having a dummy alias parameter just means ctfeOnly.

May 12, 2020
On Tuesday, 12 May 2020 at 14:14:21 UTC, Stefan Koch wrote:
> On Tuesday, 12 May 2020 at 11:39:04 UTC, Johannes Loher wrote:
>
>> Honestly, to me this sounds like a total mess. If templates allow binding alias to a value, so should type functions, or they should use a different name than "alias". Otherwise it's just confusing. To me it looks like for type functions, you think of "alias" as something like the "type of types". But for alias template parameters and alias declarations it is something completely different (as Steven  explained, it is an unrestricted compile-time name). For example, consider the following: [ ... ]
>
> are you sure that that is the case for alias declarations?
> For me
> alias a = "Foo";
> causes Error: basic type expected, not "Foo"
> Which is identical to how they behave in type functions;

You are right, the language is already inconsistent in that regard. However, the following works:

void main()
{
    static immutable x = 0;
    alias other_x = x;
    static assert(other_x == 0);
}

So type functions should support at least that much (I don't know if they do in what you have in mind right now):

auto typeFun(alias x)
{
    return x == "foo";
}

void main()
{
    static immutable x = "foo"
    static assert(typeFun(x));
}

Let's not create a third meaning for "alias"... Rather we should unify the 2 meanings that exist right now.
May 12, 2020
On 5/12/20 12:20 PM, Stefan Koch wrote:
> On Tuesday, 12 May 2020 at 16:12:42 UTC, Steven Schveighoffer wrote:
> 
>> to force a type function instead of using CTFE when you want to manipulate a compile-time list of strings.
>>
>> It reminds me of what people would resort to for a static foreach over a tuple when all they wanted was the index (before static foreach existed).
>>
> 
> There is no essentially no difference between a type function and CTFE.
> Type functions are really just passing type as expressions to CTFE.
> Well that and the ability to assign to alias.
> Having a dummy alias parameter just means ctfeOnly.
> 

Right. What I meant was, a function that is intended ONLY to be used for ctfe could put in a dummy parameter, or they could take the string array as an alias[] (if it's supported), and have it support more than just string arrays.

It would be awkward and confusing to have a different set of functions or constructs to deal with type lists than ones that deal with values (or mixed lists). Not only that, but it's also odd for aliases to work differently here than they do in templates.

-Steve
May 12, 2020
On Tuesday, 12 May 2020 at 16:12:42 UTC, Steven Schveighoffer wrote:
> I can totally envision this pattern happening:
>
> string foo(string[] symbolnames, alias dummy = __dummy)
> {
>    // do something with symbolnames, ignore dummy
> }
>
> to force a type function instead of using CTFE when you want to manipulate a compile-time list of strings.
>

Why would you ever do this? To enforce that the function is only called at compile time? Looks like a hack to a problem we should have a proper solution for instead.
May 12, 2020
On 5/12/20 1:32 PM, Johannes Loher wrote:
> On Tuesday, 12 May 2020 at 16:12:42 UTC, Steven Schveighoffer wrote:
>> I can totally envision this pattern happening:
>>
>> string foo(string[] symbolnames, alias dummy = __dummy)
>> {
>>    // do something with symbolnames, ignore dummy
>> }
>>
>> to force a type function instead of using CTFE when you want to manipulate a compile-time list of strings.
>>
> 
> Why would you ever do this? To enforce that the function is only called at compile time?

I'm assuming in type functions we have further leeways that aren't available in CTFE functions. Like, for instance, SomeTemplate!(symbolnames[0]) should be doable in a type function, but would not be doable in a CTFE function.

Not sure if that would require symbolnames be an alias[] or not.

> Looks like a hack to a problem we should have a proper solution for instead.

I agree, which is why I brought it up.

-Steve
May 12, 2020
On Tuesday, 12 May 2020 at 19:15:54 UTC, Steven Schveighoffer wrote:
> On 5/12/20 1:32 PM, Johannes Loher wrote:
>> On Tuesday, 12 May 2020 at 16:12:42 UTC, Steven Schveighoffer wrote:
>>> I can totally envision this pattern happening:
>>>
>>> string foo(string[] symbolnames, alias dummy = __dummy)
>>> {
>>>    // do something with symbolnames, ignore dummy
>>> }
>>>
>>> to force a type function instead of using CTFE when you want to manipulate a compile-time list of strings.
>>>
>> 
>> Why would you ever do this? To enforce that the function is only called at compile time?
>
> I'm assuming in type functions we have further leeways that aren't available in CTFE functions. Like, for instance, SomeTemplate!(symbolnames[0]) should be doable in a type function, but would not be doable in a CTFE function.
>
> Not sure if that would require symbolnames be an alias[] or not.
>
>> Looks like a hack to a problem we should have a proper solution for instead.
>
> I agree, which is why I brought it up.
>
> -Steve

Actually no.
If you did that you would be passing a variable to a template which expects a type.
Type functions are not magic and they are not dynamically typed.

Their purpose is to offer an alternative for introspection usecases.
In which the genericty of templates is not needed and the compiler is unwanted.
There no way to make a type out of a type variable.
Because that would require a dynamic type system.

Type functions provide a compile time interface to introspection abilities without incurring the cost of templates, and providing the option to write code in imperative programming style.

@johannes I have put some thought into how this will interact and so far the simplicity of the implementation seems to point towards very nice interplay as well.

When there is more of a full featured implementation I will present a more formal discussion about the topic.