groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From MG <mg...@arscreat.com>
Subject Re: Fwd: About supporting `var` of Java10+
Date Sat, 10 Mar 2018 19:33:19 GMT
Hi Jochen,

I was not aware that Groovy is so sophisticated in its expression 
analysis, that it actually uses intersection types - I had assumed it 
would fall back to Object in these cases :-)
Much of what Groovy does here is of course obscured by Intellisense 
warnings ;-)
(btw @daniil.ovchinnikov@jetbrains.com: Is that parser completely 
independent, or is it based on Groovy, CodeNarc, etc code ?)


I thought of a possible entirely different rout to take for "var" in the 
dynamic case, namely that var could be forbidden in dynamic case (based 
on the fact that it makes little to no sense), throwing a CTE like:
"'var' is not supported in dynamic Groovy code. Annotate the 
method/class with @CompileStatic to switch to static compilation, or 
replace 'var' with 'def'."
Rationale:

 1. Var can currently only come from Java code copy & pastedinto Groovy
    code. This CTE would give a hint to the person doing that, that
    Groovy has a static compilation mode, and that if he is coming from
    Java, that is maybe what he actually wants to use, to semantically
    as close to Java as possible (and not have e.g. stuff like
    null.forEach {} being valid code).
 2. It does not hinder Groovy in any way, since there is no reason for
    anyone programming dynamic Groovy to use var instead of def.
 3. It would, on the other hand, allow to introduce var support not
    based on var === def to dynamic Groovy later on, without breaking
    backwards compatibility (because  var x = new Foo(); x = 123
    suddenly does not work any more)


Just food for thought - I personally would prefer to see the "90% 
solution" I talked about in an earlier post for dynamic Groovy:
Support var x = RHS -> typeof(RHS) x = RHS for simple cases, such as:
var x = new Foo(...)
var x = (Foo) ...
var x = foo(...) // use the explicit return type of method foo(), CTE on 
return type == def ("'var' not supported for 'def' as return type - use 
Object as return type of method or define variable using 'def'.")
throw CTE in all other cases (least surprise - "'Type for variable 
defined with 'var' cannot be deduced in dynamic Groovy. Annotate the 
method/class with @CompileStatic to switch to static compilation, or 
replace 'var' with 'def'."

Maybe I am seeing things too rosy, but I feel that dynamic Groovy should 
not completely loose out on var.
 From the view of my framework code that goes even more so for the 
related case of final x = RHS -> final typeof(RHS) x = RHS I therefore 
keep going on about - if dynamic Groovy does not pick up the RHS type 
for final, I need to keep my current code, or force framework users to 
use @CompileStatic on all Table derived classes, if they want to define 
table columns in the most elegant and concise way... :-)
mg




On 10.03.2018 14:23, Jochen Theodorou wrote:
> On 10.03.2018 03:51, Paul King wrote:
>>
>> Hi, sorry I meant to respond to the list too. Messages included below.
>>
>> ---------- Forwarded message ----------
>> From: *MG* <mgbiz@arscreat.com <mailto:mgbiz@arscreat.com>>
>> Date: Sat, Mar 10, 2018 at 7:19 AM
>> Subject: Re: About supporting `var` of Java10+
>> To: paulk@asert.com.au <mailto:paulk@asert.com.au>
> [...]
>> # Intersection types are especially difficult to map to a 
>> supertype—they're not ordered, so one element of the intersection is 
>> not inherently "better" than the others. The stable choice for a 
>> supertype is the lub of all the elements, but that will often be 
>> Object or something equally unhelpful. So we allow them.
>>
>> I have never used intersection types. I would really be interested to 
>> know how many people have ever used them.
>> I tried the following in Groovy, but got a
>
> if you have for example this:
>
> def x
> if (b) {
>   x = y;
> } else {
>   x = z;
> }
> x.foo()
>
> then what is the type for x, to check if foo() is an allowed method? 
> The answer in Groovy is, it is the LUB(type(z),type(y)). The result 
> might be an intersection type for x, that for example consists of 
> Object and all interfaces the two have in common.
>
> [...]
>> # Anonymous class types cannot be named, but they're easily 
>> understood—they're just classes. Allowing variables to have anonymous 
>> class types introduces a useful shorthand for declaring a singleton 
>> instance of a local class. We allow them.
>>
>> How do you assign a new value to a variable that has a type that 
>> exists only once:
>
> In Java with var you don´t
>
> [...]
>> Maybe I am overlooking something, but using the anonymous type here 
>> looks like it would effectively make the variable final. So it looks 
>> like using the non-anonymous super class might make more sense here 
>> (it would not break Java compatibility, and would give programmers 
>> more options, if final is also changed in Groovy to use the RHS type 
>> instead of Object).
>
> I can do
>
> var x = new Object() {
>   public void foo(){}
> };
> x.foo();
>
> Using Object for x, does no longer allow you to call foo(). The only 
> variant this can be made work in Java right now is by not using an 
> anonymous inner class. This here is the "declaring a singleton 
> instance of a local class" that is intended to be allowed.
>
>>> So some of the simple immediate implications are:
>>> * error if var used for fields
>>
>> As I said supporting that would feel Groovy to me, so if it is easy 
>> to do I would support it, but I don't see it as essential in any way.
>
> In a field declaration like "var x = 1" we can do it. We cannot do it 
> for the anonymous inner class, if we are supposed to take the specific 
> class. We cannot do it for intersection like types, because we need a 
> real type to give to the field. We cannot do it if the initialization 
> is in more than one place (multiple constructor for example) and 
> probably a few more. I would definitely go without this first.
>
> [...]
>>> The devil will be in the detail when we try to update the type checker
>>
>> I assume the replacement
>> var x = RHS
>> becoming
>> typeof(RHS) x = RHS
>> cannot be done before the type checker runs ?
>
> nope
>
>>> - and for dynamic Groovy I suspect we might need some additional 
>>> restrictions in addition to those chosen by Java.
>>
>> Stupid question: Why ?-)
>> Isn't the dynamic case just
>> 1) var -> typeof(RHS)
>> 2) done
>> ?
>
> I think for dynamic Groovy we should do var == def. we cannot do var 
> -> typeof(RHS), because we may not know the RHS type at compile time. 
> And at runtime the RHS type is really not of that much use anymore.
>
> But for me that means the more restricted one is var in static 
> compilation, not dynamic.
>
> bye Jochen
>


Mime
View raw message