## digitalmars.D - Tuple IFTI with implicit conversions

• Reiner Pope (49/59) Oct 19 2007 (A follow-up from "Any ideas for lazy evaluation on varaible argument
• BCS (7/24) Oct 19 2007 [...]
• Reiner Pope (4/30) Oct 20 2007 Yes, I think what you suggest is nicer, since it works equally well for
• Janice Caron (2/2) Oct 19 2007 What does IFTI stand for?
• BCS (8/10) Oct 19 2007 implicit function itemplate instantiatein
• Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= (19/80) Oct 20 2007 Couldn't the polysemous values be used here? E.g. caller side calls the
• BCS (31/53) Oct 20 2007 Yeah, I like that syntax a little better than mine (I never did like min...
• Reiner Pope (48/133) Oct 20 2007 In their simplest form, predicates solve a different problem. To give a
```(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?

---
[1]: Here's what I mean when I distinguish parameter and argument types:

void foo(long x) { ... }

void main()
{
int y;
foo(y);
}

Here, I call long the parameter type, and int the argument type. The
distinction is that the argument type is the type of the expression at
the call site.

-- Reiner
```
Oct 19 2007
```Reply to Reiner,

(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[]).

[...]

LOL

Take a look at my replay to Daniel Keep's post

in short, I just suggested a slightly more general form of the exact same
idea.

What do you think?

I'm for it. (clearly)
```
Oct 19 2007
```BCS 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[]).

[...]

LOL

Take a look at my replay to Daniel Keep's post

in short, I just suggested a slightly more general form of the exact
same idea.

Yes, I think what you suggest is nicer, since it works equally well for

-- Reiner
```
Oct 20 2007
```What does IFTI stand for?
(Even Google doesn't seem to know)
```
Oct 19 2007
```Reply to Janice,

What does IFTI stand for?
(Even Google doesn't seem to know)

implicit function itemplate instantiatein

it's what lets you skip the template args sometimes.

int foo(T)(T t){...}

// full form
foo!(int)(5);

// with ITFI
foo(5);
```
Oct 19 2007
Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
```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
```
Oct 20 2007
```Reply to Jari-Matti Mäkelä,

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.

Yeah, I like that syntax a little better than mine (I never did like mine,
to many T's) but I'm not clear on the semantics. How would it map the "used"
types to the "accepted" types?

what I want is to work:

void TFn(T)(T a, T b){...}

// 'A' converts to 'B', 'B' doesn't convert to 'A'

A a;
B b;
TFn(a, b);
TFn(b, a);

the first though is to map by position:

void TFn(T, U)(TypeFn!(T, U) a, TypeFn!(T, U) b){...}

but what if there a different number of template args than function args?

void TFn(V, T, U)(V v1, F!(T,U, V) a, V v2, F!(T,U) b){...}

now what?

what is needed is a way to get at explicitly bind something to the incoming
type. An interesting note here is that the this is close to a system where
the actual template args can be derived from what is given, this can result
in fewer instances of the template.

Av get(Av : (uint N = Av.length, T = typeof(Av[0])))(T[] text)
{
if(text.length < N) return null;
return text[0..N];
}

TestFor!("hello")(str);  // same function
TestFor!("world")(str);  // in both cases

I'm not sure where this is all going, but I see a huge amount of power in
letting the programer get ahold of the types and value that the user gives
and play with them, particularly if this can work with the ITFI.
```
Oct 20 2007
```Jari-Matti Mäkelä wrote:
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

In their simplest form, predicates solve a different problem. To give a
concrete example of what I'm talking about, suppose I have a struct:

struct Wrapper(T)
{
const bool IsWrapper = true;
...
static Wrapper!(T) opImplicitCastFrom(T t) {...}
}

and I have a function which requires that it is called with arguments
always wrapped in Wrapper (Wrapper!(T) might, for instance, be lazy(T),
or a reference to T, so that it has to be wrapped on the calling side).

Suppose you had a predicate which said if some type, T, is a Wrapper of
something else. It might look like:

template WrapperPredicate(T)
{
const bool WrapperPredicate = is(T.IsWrapper == bool);
}

If you then wrote a templated function using this predicate, it wouldn't
work:

void foo(T : WrapperPredicate!(T)) (T t) {}

void main() {
foo(5); // error, int is not a Wrapper, so no template found
}

This seems to be where you say polysemous values help, ie when
instantiating the template, you come up with a list of possible types
for T, and see if any match the predicate. The problem is that this list
can be infinitely long, if you have something like this:

struct Foo(T)
{
static Foo!(T) opImplicitCastFrom(int i) {...}
}

While that might be a straw man, it still highlights the difficulty in
the compiler being able to find that Wrapper!(int) has an
opImplicitCastFrom(int). I think templates are too powerful for the
compiler to determine all the possible implicitly-convertible types, so
for problems like this, you need to say to the compiler, "here's how you
find the type". Predicates alone don't do this, as they just say, "this
type is (in)valid".

Interestingly, C++0x Concepts have concept_maps, which solve this
problem by letting you tell the compiler "this is how to make this type
match this concept."

---

However, I agree with you about the need for predicates. There's a neat
trick which allows you to use them already in D, though:

void foo(T, bool T_predicate : true = IsValidParam!(T)) (T t) {...}

It works well, except that it doesn't allow specialization.

-- Reiner
```
Oct 20 2007
Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
```Reiner Pope wrote:

In their simplest form, predicates solve a different problem. To give a
concrete example of what I'm talking about, suppose I have a struct:

struct Wrapper(T)
{
const bool IsWrapper = true;
...
static Wrapper!(T) opImplicitCastFrom(T t) {...}
}

and I have a function which requires that it is called with arguments
always wrapped in Wrapper (Wrapper!(T) might, for instance, be lazy(T),
or a reference to T, so that it has to be wrapped on the calling side).

Suppose you had a predicate which said if some type, T, is a Wrapper of
something else. It might look like:

template WrapperPredicate(T)
{
const bool WrapperPredicate = is(T.IsWrapper == bool);
}

If you then wrote a templated function using this predicate, it wouldn't
work:

void foo(T : WrapperPredicate!(T)) (T t) {}

void main() {
foo(5); // error, int is not a Wrapper, so no template found
}

This seems to be where you say polysemous values help, ie when
instantiating the template, you come up with a list of possible types
for T, and see if any match the predicate. The problem is that this list
can be infinitely long

Agreed, calculation of the lists might become intractable. On the other hand
you could extend the predicate here to accept both, wrappers and
primitives. Then the intractability would depend on the search method.

However, I agree with you about the need for predicates. There's a neat
trick which allows you to use them already in D, though:

void foo(T, bool T_predicate : true = IsValidParam!(T)) (T t) {...}

Yep, and this syntax seems to make more sense since it allows you to specify
predicates independently of the other template parameters.

It works well, except that it doesn't allow specialization.

True (at least in the case of IFTI), but I meant the predicate would allow
specialization with and without IFTI. It would also use similar semantics
to IsExpression:

void foo(T)(T T) { ... } // 1)
void foo(T, isValidParam!(T) == true)(T t) { ... } // 2)

Now when isValidParam!(T) evaluates to true, 2) would be selected, otherwise
1). Again the syntax isn't probably as good as it could be.
```
Oct 21 2007