Tuple IFTI with implicit conversions
Jari-Matti Mäkelä
jmjmak at utu.fi.invalid
Sat Oct 20 11:31:52 PDT 2007
Reiner Pope wrote:
> (A follow-up from "Any ideas for lazy evaluation on varaible argument
> functions?")
>
> Daniel Keep wrote:
>> Sadly, I don't think there's any way to fix this. The problem is that
>> if you've got IFTI (which is what allows you to omit the explicit
>> template instantiation), the arguments can't be very complex. What you
>> would need is something like this:
>>
>> void infoF(A...)(lazy DecayStaticArrays!(A) a) { ... }
>>
>> Where "DecayStaticArrays" turns all statically-sized arrays into
>> dynamically-sized ones: so (char[2u], char[6u]) would become (char[],
>> char[]).
>
> This kind of problem with IFTI seems to come up from time to time. I
> think the general case of this problem is when you want the parameter
> types[1] to be something which the argument types[1] are implicitly
> convertable to. This could be like the example above (where char[6u] is
> implicitly convertable to lazy char[]) or perhaps some function which
> takes the biggest integer type of the parameters:
>
> BiggestIntType!(A) max(A...)(BiggestIntType!(A)[] params...) { ... }
>
> Unfortunately, the above function won't work with IFTI. Normally, the
> "standard" solution to this would be to have a wrapper template:
>
> BiggestIntType!(A) max(A...)(A a) {
> max_impl!(A)(a);
> }
>
> BiggestIntType!(A) max_impl(A...)(BiggestIntType!(A)[] params...) { ... }
>
> so that the wrapper ensures IFTI still works, and it simply passes on
> the argument types to the wrapper. Although this solution works here, it
> doesn't solve Daniel's problem, and it ends up being repeated whereas I
> think the language should essentially support doing it for you.
>
> More valuable would be the existence of some tuple in a function
> template which was a tuple of the argument types[1] for a function. I'm
> not fussed about the syntax, but the point is that argtypes is simple to
> evaluate: just take typeof() of each of the argument expressions at the
> call-site, and stick them together as a tuple. Since there's no pattern
> matching involved, IFTI can't fail. So, the examples above would become:
>
> BiggestIntType!(A) max (argtypes A)(BiggestIntType!(A)[] params...) { ...
> }
>
> and
>
> void infoF(argtypes A)(lazy DecayStaticArrays!(A) a) { ... }
>
> They look almost exactly the same, but the argtypes syntax says to the
> compiler, "don't try to pattern-match the parameters against lazy
> DecayStaticArrays!(A), instead just tell me what they are." Supposing
> you used the above syntax, then it would have the rules:
> 1. The argtypes parameter must always go last, even after variadic
> parameters
> 2. It is impossible to manually instantiate an argtypes parameter.
>
> What do you think?
Couldn't the polysemous values be used here? E.g. caller side calls the
function with a set of possible type tuples. In the end the compiler could
choose the best match(es) or throw an error on ambiguity. The char[] <->
char[n] conversion is particularly annoying even in very trivial code - a
template doesn't sound like a good idea.
Approach with polysemous values could be extended in other ways. IFTI
functions could be overloaded. One thing that has caused me some headache
is the IsExpression - it seems to sweep under the carpet the fact that
template parameters cannot do proper static predicate dispatching. I'd like
to see a way to specify a compile time boolean function that defines
whether the pattern matches or not (arithmetics with types should have
proper semantics then - this could be extended elsewhere too, but I won't
touch that here) - a general case could look like:
void myFun(T1 : predicate_1, ..., Tn : predicate_n)(type_1 param_1, ...,
type_n param_n)
I don't think moveing the predicates to the fn parameter side (BCS's
proposal) is a good idea since it's something different that D does now.
Here's some related discussion http://lambda-the-ultimate.org/node/1655
More information about the Digitalmars-d
mailing list