groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From MG <mg...@arscreat.com>
Subject Re: JDK 10: Use of var over def?
Date Sun, 25 Mar 2018 15:49:23 GMT
Here is an improved version of my own sample (with var keyword, i.e. 
non-executable), hopefully better exemplifying my point:

@Canonical class Foo {int x }
@InheritConstructors class SonOfFooextends Foo {int sonOfFooMethod() { ... } }
@InheritConstructors class SonOfSonOfFooextends SonOfFoo {int sonOfSonOfFooMethod() { ...}
}

SonOfFoo mayReturnSonOfSonOfFoo() { ... }

@CompileStatic void flowTypedVar() {
   var f =new SonOfFoo(21)// Transformed by compiler to: SonOfFoo f = new SonOfFoo(21); no
other 
changes to Groovy necessary f =new Foo(-1)// Fails at compile time with "Cannot assign value
of type Foo to 
variable of type SonOfFoo" f.sonOfFooMethod()// works // ... f = mayReturnSonOfSonOfFoo()//
works // ... if(finstanceof SonOfSonOfFoo) {
     f.sonOfsonOfFooMethod()// Works because of flow typing (fails at compile time in Java)
}
}

I hope that exemplifies better my thinking that var != def and flow 
typing are not necessarily either or, but orthogonal Groovy features, 
which would conceivably play well together.
I understand that you have a gut feeling that there mightbe a case out 
there where this may not hold, but until someone can come up with an 
example, I would hate to conceptually loose flow typing (which is a 
really powerful feature) just because of using var :-)

Cheers,
mg


On 25.03.2018 15:19, Paul King wrote:
> For the majority of cases, you will be able to conceptually think of 
> it as if the declaration type of the LHS is the inferred type of the RHS.
> Until we have thought about non-denotable types etc. a bit more, I 
> don't want to preempt whether a more sophisticated conceptual model 
> will sometimes be needed.
> Also, note that it isn't Object in your example but SomeTestClass$1 or 
> something like that.
>
> Cheers, Paul.
>
> On Sun, Mar 25, 2018 at 12:30 AM, MG <mgbiz@arscreat.com 
> <mailto:mgbiz@arscreat.com>> wrote:
>
>     There is no "var" in my example because it is currently valid
>     Groovy code, so I already had to do the var -> typeof(RHS)
>     substitution in the line "SonOfFoo f = new SonOfFoo(21)". I maybe
>     should have made that more explicit :-)
>     The reason I used currently valid Groovy was, that the point I am
>     trying to make is: Why should var not just become typeof(RHS),
>     while all the rest stays the same ? That should give us Java-like
>     type safety, with some added Groovy goodness...
>
>     Your example as currently working Groovy (JUnit) code through only
>     replacing var with its RHS type:
>
>     static class Main {}
>
>     @Test @Ignore @CompileStatic void main() {
>        // mg: was "var x = new Object() {" Object x =new Object() {
>          public void myMethod() { System.out.println(new Date()); } };
>     x.myMethod(); // okay because the inferred type is the AIC // mg:
>     Was "var y = new Main();" Main y =new Main();
>        y =new Main() {// reassignment okay because new type is subclass of inferred type
>     public void myMethod() { System.out.println(new Date());}
>        };
>
>        // mg: Works y.myMethod(); // <=== error: cannot find symbol //
>     mg: If commented in, fails (as expected) with "Cannot assign value
>     of type Integer to variable of type Main"//y = new Integer(3); //
>     <=== error: incompatible types: Integer cannot be converted to Main }
>
>     Cheers,
>     mg
>
>
>
>
>     On 24.03.2018 13:08, Paul King wrote:
>>     I don't see a var in your example?
>>
>>     Basically, we can use def and have flow typing (which would be
>>     the behavior if we make var always an alias for def) or we can
>>     behave like Java:
>>
>>     // Java
>>     import java.util.Date;
>>
>>     public class Main {
>>     public static void main(String[] args) {
>>     var x = new Object() {
>>     public void myMethod() { System.out.println(new Date());}
>>     };
>>     x.myMethod(); // okay because the inferred type is the AIC
>>     var y = new Main();
>>     y = new Main() { // reassignment okay because new type is
>>     subclass of inferred type
>>     public void myMethod() { System.out.println(new Date());}
>>     };
>>
>>     //y.myMethod(); // <=== error: cannot find symbol
>>                 // symbol: method myMethod()
>>                 // location: variable y of type Main
>>
>>     //y = new Integer(3); // <=== error: incompatible types: Integer
>>     cannot be converted to Main
>>     }
>>     }
>>
>>     which effectively means that we infer as we do now but no flow
>>     typing. Conceptually, you may think that in the above Java
>>     example that var y has type Main (typeof RHS) but that isn't
>>     reflected in the bytecode in the same way that a type for a field
>>     or parameter would be reflected, so it's much more a concept that
>>     the compiler knows about rather than a concept that the bytecode
>>     knows about. Currently flow typing allows both the above "error"
>>     lines to succeed. But to behave like Java, we need both to fail.
>>
>>     Cheers, Paul.
>>
>>
>>     On Sat, Mar 24, 2018 at 3:14 AM, MG <mgbiz@arscreat.com
>>     <mailto:mgbiz@arscreat.com>> wrote:
>>
>>         Hi Paul,
>>
>>         wouldn't it make sense to combine flow typing with  var x =
>>         RHS  being identical to  typeof(RHS) x = RHS  :
>>
>>         @Canonical static class Foo {
>>            int x }
>>
>>         @InheritConstructors static class SonOfFooextends Foo {
>>            int sonOfFooMethod() {2*x }
>>         }
>>
>>
>>         @Test @Ignore @CompileStatic void flowTypedVar() {
>>            SonOfFoo f =new SonOfFoo(21)
>>            //f = new Foo(-1) // compile time fails with "Groovyc:
>>         [Static type checking] - Cannot assign value of type
>>         groovy.GroovyGeneralSpike$Foo to variable of type
>>         groovy.GroovyGeneralSpike$SonOfFoo" //f.sonOfFooMethod() //
>>         compile time fails with "Groovyc: [Static type checking] -
>>         Cannot find matching method
>>         groovy.GroovyGeneralSpike$Foo#sonOfFooMethod()." if(finstanceof SonOfFoo)
{
>>              println f.sonOfFooMethod()// works because of flow typing }
>>         }
>>
>>         Cheers,
>>         mg
>>
>>
>>
>>
>>         On 23.03.2018 15:42, Paul King wrote:
>>>         The Parrot parser already has support for this at the
>>>         grammar level but we regard some of the current
>>>         implementation details as experimental.
>>>
>>>         At the moment it is almost just an alias for "def" but
>>>         discussions have been around whether we can make the
>>>         behavior closer to Java when used within static Groovy code.
>>>         We haven't defined exactly what this would mean yet but
>>>         roughly I suspect it could mean the same inferencing as now
>>>         but without flow typing.
>>>
>>>         Cheers, Paul.
>>>
>>>
>>>         On Fri, Mar 23, 2018 at 10:12 PM, Merlin Beedell
>>>         <MBeedell@cryoserver.com <mailto:MBeedell@cryoserver.com>>
>>>         wrote:
>>>
>>>             I see that the newly release JDK 10 now supports the
>>>             “var” declaration for local variables where the type can
>>>             clearly be inferred from its initialiser:
>>>
>>>             http://openjdk.java.net/jeps/286
>>>             <http://openjdk.java.net/jeps/286>
>>>
>>>             I note that Groovy’s “def” syntax (among others) was
>>>             mentioned but rejected.
>>>
>>>             Would Groovy move to support this syntax in the same way
>>>             (support ‘var’ only for Type Safe inferred declarations)
>>>             or as a general alias to the “def” keyword?
>>>
>>>             JDK 10 also has support for “docker” containers.  The
>>>             ecosystem has certainly shifted!
>>>
>>>             Merlin Beedell
>>>
>>>
>>
>>
>
>


Mime
View raw message