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.ovchinni...@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* <mg...@arscreat.com <mailto:mg...@arscreat.com>>
Date: Sat, Mar 10, 2018 at 7:19 AM
Subject: Re: About supporting `var` of Java10+
To: pa...@asert.com.au <mailto:pa...@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


Reply via email to