First life-signs of type functions

Steven Schveighoffer schveiguy at gmail.com
Tue May 12 13:24:44 UTC 2020


On 5/12/20 2:42 AM, Stefan Koch wrote:
> On Tuesday, 12 May 2020 at 01:44:45 UTC, Steven Schveighoffer wrote:
>> On 5/11/20 5:58 PM, Stefan Koch wrote:
>>>
>>> In a type function alias cannot bind to values at all.
>>> It can only bind to symbols or types.
>>
>> This seems like a problematic limitation. Aliases can bind to values 
>> when they are part of a tuple. This means that type functions are 
>> going to have to do weird template acrobatics to deal with mixed tuples.
>>
>> For a long time, alias parameters wouldn't bind to int because it was 
>> a keyword, not a symbol, even though you could alias int as a 
>> declaration. It wouldn't even bind them to aliases of int (even though 
>> they are not keywords). That has since been fixed, and everything 
>> works great. I think we should avoid arbitrary limitations like this, 
>> even if it's harder to get it to work.
>>
>> -Steve
> 
> The reason that happened is not so much a parser issue.
> But it's because Basic Types are not Symbols.
> Which is indeed a more or less arbitrary limitation.
> 
> Let's go through the reasoning for type functions now.
> let's assume alias A would bind to a value, the string foo
> for example.
> 
> string F(alias A)
> {
>      pragma(msg, typeof(A).stringof); // prints alias
>      pragma(__traits(identifier, A); // error a string has no identifer.
>      pragma(msg, is(A == string)); // prints false, because A does not 
> hold the type string
>      pragma(msg, A) prints "foo";
>      pragma(msg, A == "foo") // error can't compare alias and string
>      pragma(msg, is(A, "foo") // doesn't parse. The string "foo" is not 
> a valid identifier
>      return A; // error alias does not implicitly convert to string.
> }
> 
> You see there would not be a point in allowing that.

This is what happens now:

string F(A...)()
{
     pragma(msg, typeof(A[0]).stringof); // prints string
     //pragma(msg, __traits(identifier, A[0])); // [1] error a string 
has no identifer.
     pragma(msg, is(A[0] == string)); // prints false, because A does 
not hold the type string
     pragma(msg, A[0]); // prints "foo"
     pragma(msg, A[0] == "foo"); // prints true
     //pragma(msg, is(A[0], "foo")); // [2] doesn't parse. The string 
"foo" is not a valid identifier
     return A[0]; // works
}

enum x = F!"foo";

For [1], yeah, I get that it doesn't have an identifier. So what. Make 
the identifier null if you need it. Or it's an error and we deal with 
that. There should be mechanisms we can use to find common properties 
about everything. We already do that quite a bit with template programming.

For [2], there was some kind of syntax error. I'm not sure what it was 
you were trying to say there. The compiler complained that the comma 
wasn't valid. I don't want to assume anything for is expressions, there 
are so many forms.

If I have a function that sorts an alias[], I want it to sort 
AliasSeq!(62, 56, 23, 77) just as well as it sorts AliasSeq!(int, long, 
bool), just as well as it sorts AliasSeq!(int, 5, "hello").

The thing I want is a) mutable array instead of tuple, and b) everything 
is compile-time, so there is no "You can't use this at compile time" 
nonsense.

I was hoping that your type functions would fulfill this.

-Steve


More information about the Digitalmars-d mailing list