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