Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is wrong with inferred type of template and implicit type conversion?

I am reading "The D Programming Language" by Andrei Alexandrescu and one sentence puzzled me. Consider such code (p.138):

T[] find(T)(T[] haystack, T needle) {
   while (haystack.length > 0 && haystack[0] != needle) {
      haystack = haystack[1 .. $];
   }
   return haystack;
}

and call (p.140):

double[] a = [ 1.0, 2.5, 2.0, 3.4 ];
a = find(a, 2); // Error! ' find(double[], int)' undefined

Explanation (paragraph below the code):

If we squint hard enough, we do see that the intent of the caller in this case was to have T = double and benefit from the nice implicit conversion from int to double. However, having the language attempt combinatorially at the same time implicit conversions and type deduction is a dicey proposition in the general case, so D does not attempt to do all that.

I am puzzled because such language as C# tries to infer the type — if it cannot do this, user gets error, but if it can, well, it works. C# lives with it for several years and I didn't hear any story how this feature ruined somebody's day.

And so my questions is this — what dangers are involved with inferring types as in the example above?

I can see only advantages, it is easy to write generic function and it is easy to call it. Otherwise you would have to introduce more parameters in generic class/function and write special constrains expressing allowed conversions only for the sake of inferring types.

like image 452
greenoldman Avatar asked Nov 09 '22 17:11

greenoldman


1 Answers

The first thing to note is that it doesn't say that there's a problem with type deduction, it's that there's a problem with type deduction and implicit conversion at the same time.

So, if you have:

a = find(a, 2.0);

Then it's happy to deduce double as the type.

And if explicitly typed for double, it's happy to deduce that 2 should be implicitly cast to 2.0.

What it's not going to do is both at the same time.

Now, C# does do that. And I think for the most part I agree with you, it's generally convenient and generally works well enough.

It is true at the same time that it can be confusing, especially in cases where it leads to more than one equally reasonable overload.

Why type inference and implicit operator is not working in the following situations? and Why does Assert.AreEqual on custom struct with implicit conversion operator fail? are both questions about why a particular combination of implicit conversion and type inference didn't work.

Unexpected effect of implicit cast on delegate type inference has other factors, but again just refusing to consider the method in the list of possible matches because the argument type didn't match would mean the problem didn't happen.

They'd both be a lot simpler if the answer was always "because you are doing implicit conversion and type inference at the same time, and that's not supported". Which is what the answer would be with D.

On the other hand though, such problems don't arise that often, so I still favour the C# design decision to allow for both, but that there are some problems means it's still a reasonable design decision to not allow them.

like image 86
Jon Hanna Avatar answered Nov 15 '22 08:11

Jon Hanna