tuple of delegates requires explicit type

DigitalDesigns DigitalDesigns at gmail.com
Wed Jun 20 15:19:29 UTC 2018


On Wednesday, 20 June 2018 at 12:08:28 UTC, Jonathan M Davis 
wrote:
> On Wednesday, June 20, 2018 11:43:52 DigitalDesigns via 
> Digitalmars-d wrote:
>> alias f = void delegate();
>> Tuple!(f)[] fs;
>>
>> fs ~= tuple(() { });
>>
>> fails but
>>
>> fs ~= Tuple!(f)(() { });
>>
>> passes.
>> in tuple, it is seeing the lambda as void and thinks I'm trying
>> to append a tuple of void. I don't see why the compiler can't 
>> see
>> that it works.
>
> The types don't match.
>
> ---
> import std.typecons;
>
> alias f = void delegate();
>
> void main()
> {
>     pragma(msg, typeof(tuple((){})));
>     pragma(msg, typeof(Tuple!f((){})));
> }
> ---
>
> prints
>
> Tuple!(void function() pure nothrow @nogc @safe)
> Tuple!(void delegate())
>
> tuple is instantiated and evaluated independently of what's 
> done with the result, so the fact that you're then appending it 
> to a Tuple!f[] is irrelevant. By the point it tries to append, 
> it's already determined the type of what it's trying to append, 
> and because you didn't specify the type, it's what it gets 
> inferred as, which is not the same type as you have in the 
> array.
>
> - Jonathan M Davis

But here's the kicker!!! Trust me, it will be good!!

They are the same types! That alone says that the compiler is not 
doing enough work! I mean, it is well established that the array 
is of type f and the lambda is of type f!!

See, what the compiler is not doing is realizing that a lambda 
can be implicitly cast to any other lambda with the same 
signature. If it understood that then it should have no problem 
with casting the tuple implicitly.


> Tuple!(void function() pure nothrow @nogc @safe)
> Tuple!(void delegate())

a function can always be cast to a delegate(delegate is a super 
type as it inherits function in type logic) and the lambda may be 
a function or delegate depending on context. Hence the compiler 
can always assume an implicit cast of functions to delegates when 
type checking on tuple.

This seems to be the missing logic either in the compiler or 
possibly with tuple. If tuple could support an implicit cast or 
simply upcast all functions to delegates then the code would 
work...

but it seems tuple does no upcasting.

Tuple!(double)[] f;
f ~= tuple(3); // change 3 to 3.3 and it works fine!

has the same problem. We know int inherits from double(it is a 
sub-type in the class of types).

This is the same problem as general implicit casting which D can 
do.

Just seems that it fails for tuples because it does not apply the 
implicit casts per argument.

It's easy to see that if one has n types in a tuple then it can 
be implicitly converted if all the types are implicitly converted.


Conv(T(a1,...,an)) = T(Conv(a1),...,Conv(an))







More information about the Digitalmars-d mailing list