groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From MG <mg...@arscreat.com>
Subject Re: About type inference of method return value
Date Thu, 06 Sep 2018 00:23:24 GMT
Hi Jochen,

but in what sense is any of these examples confusing for the user ? Type 
inference is not magic, and it can quickyl become a hard mathematical 
problem (https://en.wikipedia.org/wiki/Type_inference). But in all that 
cases, we should just fall back to Object or throw. I don't know 
Daniel's intentions, but for me type inference for methods (same as for 
fields/variables) should only be used for simple, obvious cases, not for 
complex ones (eveb if these are of course the only interesting 
intellectual challnge ;-) ). If I, as a developer, cannot see the 
deduced type at a a glance, then the RHS expression is already too complex.

I have added some comments to the examples:

On 05.09.2018 23:03, Jochen Theodorou wrote:
>
>> private foo() {
>>   return new SomeMarkerInterface(){
>>     def x() {1}
>>   }
>> }
>
> is the return type here SomeMarkerInterface or XYZ$1? 

XYZ$1

> Can I do foo().x()?

yes

>
>> private foo() {
>>   if (something) {
>>      return x // of class X
>>   } else {
>>      return y // of class Y
>>   }
>> }
>
> if X and Y implement the interfaces Foo and Bar the common super type 
> would be something like Object+Foo+Bar, which cannot be an actual 
> return type, because the Java type system cannot properly express that 
> type. Which is it then? Object, or Foo or Bar? 

Intuitively I would not infer on interfaces, but only classes. In 
practice I would expect X and Y to have a common superclass that is not 
Object; otherwise infer Object.

> And if you think this problem is small, you have to consider this one 
> here as well:
>
>> private foo() {
>>   def ret
>>   if (something) {
>>      ret = x // of class X
>>   } else {
>>      ret = y // of class Y
>>   }
>>   return ret
>> }
>
> Same problem as before obviously, just showing that using local 
> variables makes it even worse.

Infer Object - if you use Object for the return variable type, this is 
what you should expect...


>
> And how about this one?
>
>> private f(List<X> l) {   if (l.size()==1) {
>>     return l[0]
>>   } else {
>>     return f(l.tail())
>>   }
>> }
>
> for me it is obvious the return type is X, but a compiler must be able 
> to see through the recursive call and it must see that it is a 
> recursive call.

Too complex => infer Object

>
>> private f(List<X> l) {   if (l.size()==1) {
>>     return g(l[0])
>>   } else {
>>     return g(f(l.tail()))
>>   }
>> }
>> private g(X x){x}
>> private g(List<X> l){l}
>
>
> here it gets even more complicated... g(l[0]) is easy, that will 
> return X, since l[0] will return X causing a call to g(X):X. But since 
> we currently infer f, we cannot simply know what f(l.tail()) will be, 
> thus we cannot easily know if we call here g(X):X or g(List<X>):List<X>.

Way too complex and ambivalent => throw 
GroovyMethodReturnTypeInferenceComplexityError telling programmer he 
must supply the return type explicitely (optional: compiler parameter to 
infer Object in these cases)

>
> Or let us say there is also g(Object):Object and let us assume we 
> delete g(X):X. Then inferring the type above successfully means 
> obviously to let f return Object. The change will go unnoticed in f 
> and cause secondary errors in callers of f. In the worst case even 
> quite far away from the callsite itself.

I do not follow: What secondary errors would that be ? How would they 
differ from errors that occur when the user explicitely supplies Object 
as return type ?

>
> Wanting more?
>
>> private f(List<X> l) {   if (l.size()==1) {
>>     return l[0]
>>   } else {
>>     return g(l.tail())
>>   }
>> }
>> private g(List<X> l){f(l)}
>
> to know the return type of f I need to know the return type of g, for 
> which I need to know the return type of f... global type inference 
> could solve such problems, but makes about everything else more 
> complicated

GroovyMethodReturnTypeInferenceComplexityError...

Cheers,
mg








Mime
View raw message