When support for var was installed, the path taken was to make it work more or 
less like def.  That is not to say it is identical to def, since we did make 
sure to support the name "var" — reserved type name and not keyword.  This was 
a fitting choice given our close-to-Java semantics.  We don't want 
compatibility issues, but some do exist.

The way def works is to indicate a "dynamic type" in most cases.  This is 
equivalent to java.lang.Object in many circumstances.

I understand your request to have var work everywhere that def does so you can 
stop using def altogether.

My preference would be for var to be used for the same local variable 
circumstances that Java defines.  But we have not implemented the type 
inference that Java provides; STC gives a close approximation.

So if you can use var for field/property, I would consider deprecating and 
later removing that.  It may not have been intentional since the grammar shares 
rules for fields and variables.

________________________________
From: Gianluca Sartori <g.sart...@gmail.com>
Sent: Thursday, November 21, 2024 2:39 PM
To: dev@groovy.apache.org <dev@groovy.apache.org>
Subject: Re: [EXT] Re: Using `var` as method return type placeholder

If we want Groovy to just accept `var` as it is used in Java we should also 
reject an un-initialized variable definition or a "var v = null' since the type 
cannot be inferred and it would not be accepted by Java.

My take on this argument is that "Groovy digests Java but Groovy is not Java" 
and instead of talking about "semantics" we may talk about "lexicon' when 
discussing about `def` (Python lexicon) and `var` (Java lexicon) but the 
semantics remains the same: they are both "type placeholders" in Groovy.



Gianluca Sartori
--
Cell. +39 388 1026822


On Thu, 21 Nov 2024 at 21:25, Gianluca Sartori 
<g.sart...@gmail.com<mailto:g.sart...@gmail.com>> wrote:
Using `var` for fields or properties is less meaningful than using `var` as a 
type placeholder for methods. I can understand that the word "(var)iable" is 
semantically more specific than the word "(def)ine" but it is not that ugly or 
alien in method definitions if we think of `var` as a placeholder for 'Object' 
(like what is `def` today).

If we want Groovy to "just" accept and compile Java code we should accept `var` 
only for local variables.

What I am proposing though is that we use `var` as "the new `def`" so if we 
want to write code "the Python-ish way" we use `def`, if we want to write code 
"the Java-ish way" we use `var`.


Gianluca Sartori
--
Cell. +39 388 1026822


On Thu, 21 Nov 2024 at 20:48, Jonathan Carter 
<jonathanccar...@gmail.com<mailto:jonathanccar...@gmail.com>> wrote:
The Oracle docs on 
var<https://urldefense.com/v3/__https://docs.oracle.com/en/java/javase/17/language/local-variable-type-inference.html__;!!GFN0sa3rsbfR8OLyAw!fVG_R8uSV1w8CBE28pxva8IPqDXIa3kKPXm4EjFrGpedbb-Pa2pkpPYmYnvElEsS1Xl1-4ATLOWNvnFzCl3pidAa$>
 are helpful, here. Specifically, this part:

var can be used for the following types of variables:

  *
Local variable declarations with initializers:
  *
Enhanced for-loop indexes:
  *
Index variables declared in traditional for loops:
  *
try-with-resources variable:
  *
Formal parameter declarations of implicitly typed lambda expressions: A lambda 
expression whose formal parameters have inferred types is implicitly typed:
  *
In JDK 11 and later, you can declare each formal parameter of an implicitly 
typed lambda expression with the var identifier:

In short, `var` is purely a local variable placeholder in Java.

Given that Java carefully limited var to work as a reserved type name, not a 
keyword to avoid interfering with existing code that used var as a variable 
name, I do think there's potential for semantic surprise with Java if Groovy 
expands it out to be a synonym for def. The Groovy 
semantics<https://urldefense.com/v3/__https://groovy-lang.org/semantics.html__;!!GFN0sa3rsbfR8OLyAw!fVG_R8uSV1w8CBE28pxva8IPqDXIa3kKPXm4EjFrGpedbb-Pa2pkpPYmYnvElEsS1Xl1-4ATLOWNvnFzCgg5WHYn$>
 documentation that Gianluca refers to doesn't really advertise using var for 
fields or properties either, even if it does happen to work. Indeed, the 
warnings around how type inference works (or doesn't) for 
fields<https://urldefense.com/v3/__https://groovy-lang.org/semantics.html*_variables_vs_fields_in_type_inference__;Iw!!GFN0sa3rsbfR8OLyAw!fVG_R8uSV1w8CBE28pxva8IPqDXIa3kKPXm4EjFrGpedbb-Pa2pkpPYmYnvElEsS1Xl1-4ATLOWNvnFzCmjwZaoW$>
 makes me question whether we would want it to. Imagine the case of a Java 
developer seeing, "Oh, I can declare a field with var, assign its value 
immediately, and get type inference!" only for that to fail.

I suspect that saying "def and var are basically just Object" probably isn't 
helpful in the documentation, and leads to this surprising case that Gianluca 
has run into here. This is a subjective case, and what surprises you depends a 
lot on your background, but my hunch on the "least surprising" thing to do for 
most people would be to document that "var is only for local variables, just 
like Java" and treat its validity for fields as an undocumented, possibly even 
a deprecated behavior. The note from the aforementioned doc is relevant:

Why such a difference? The reason is thread safety. At compile time, we can’t 
make any guarantee about the type of a field. Any thread can access any field 
at any time and between the moment a field is assigned a variable of some type 
in a method and the time is used the line after, another thread may have 
changed the contents of the field. This is not the case for local variables: we 
know if they "escape" or not, so we can make sure that the type of a variable 
is constant (or not) over time. Note that even if a field is final, the JVM 
makes no guarantee about it, so the type checker doesn’t behave differently if 
a field is final or not.

This is one of the reasons why we recommend to use typed fields. While using 
def for local variables is perfectly fine thanks to type inference, this is not 
the case for fields, which also belong to the public API of a class, hence the 
type is important.

Groovy may be more liberal than Java, but it seems like we'd still want to 
steer people away from assuming "type inference works everywhere! I'm 
freeeeeeee!"

Best,

Jonny

On Thu, Nov 21, 2024 at 12:27 PM most m 
<ubermenc...@gmail.com<mailto:ubermenc...@gmail.com>> wrote:
@Steve Etchelecu

Java's var is a purely local type placeholder to elide the well-known verbosity 
when declaring and initializing variables on the same line, e.g. so that 
instead of writing "VeryLongTypename variable = new VeryLongType name(...);", 
you could omit the variable's type declaration and leave it be inferred from 
the initializer expression.

I don't think javac considers it valid anywhere except a declare-and-initialize 
statement and a foreach loop iterator declaration.

On Thu, Nov 21, 2024, 20:17 Steve Etchelecu 
<steve.etchel...@gmail.com<mailto:steve.etchel...@gmail.com>> wrote:
I thought Gianluca made an excellent argument and helps modernize the language. 
 Given Groovy’s symbiotic relationship with Java, it seems like the guidance 
here should probably be to follow Java’s usage as that likely keeps 
friction/confusion to a minimum.

Not being a Java developer, it isn’t clear to me whether Java supports var as a 
return type though I assume it does for consistency.

On Nov 21, 2024, at 11:10, Milles, Eric (TR Technology) via dev 
<dev@groovy.apache.org<mailto:dev@groovy.apache.org>> wrote:


I don't think semantically that "var name() { ... }" makes sense.

One might argue that var for field and property do not make sense either.  We 
could explore removing support for var on class members.
________________________________
From: Gianluca Sartori <g.sart...@gmail.com<mailto:g.sart...@gmail.com>>
Sent: Thursday, November 21, 2024 10:57 AM
To: dev@groovy.apache.org<mailto:dev@groovy.apache.org> 
<dev@groovy.apache.org<mailto:dev@groovy.apache.org>>
Subject: [EXT] Re: Using `var` as method return type placeholder

External Email: Use caution with links and attachments.

Well, actually that's not true, Groovy supports creating fields and properties 
as well with `var`, so basically everything `def` does except return types.


Gianluca Sartori
--
Cell. +39 388 1026822


On Thu, 21 Nov 2024 at 17:41, Daniel Sun 
<sun...@apache.org<mailto:sun...@apache.org>> wrote:
Hi Gianluca,

     `var` was introduced to Groovy just for the better compatibility of Java. 
Java just supports declaring variables with `var`, so does Groovy.

Cheers,
Daniel Sun

On 2024/11/21 10:37:23 Gianluca Sartori wrote:
> Hello everybody,
>
> My name is Gianluca Sartori, from Italy, I am the author of the open source
> project Dueuno Elements 
> (https://github.com/dueuno-projects/dueuno-elements<https://urldefense.com/v3/__https://github.com/dueuno-projects/dueuno-elements__;!!GFN0sa3rsbfR8OLyAw!dKLiRGGSN06yuMZYXThMMGLu5ES8nh1240B7mX97feXlJsWHlparG8WQWaFKj2SCDpw5PVXgiTa1KWx0GZNXc3SM$>)
> and I am new to this list.
>
> I would like to start using the more Java-ish `var` instead of the
> Python-ish `def` lexicon but I came across the fact that I cannot use `var`
> as method return type placeholder.
>
> My understanding is that I can use `var` for both local variables and class
> fields/properties but I cannot use it, for example, if I want to have a
> read only property. The code below does not compile:
>
> class C {
>     var firstname
>     var lastname
>
>     var getFullname() {
>         return firstname + ' ' + lastname
>     }
> }
>
> var c = new C(firstname: 'Gianluca', lastname: 'Sartori')
> c.fullname
>
> I'd like to switch to using `var` as a type placeholder, but having to use
> `var` for variable declaration and keep using `def` for methods definition
> is something I don't understand. I love Groovy because it is easy. This
> restriction of the `var` type placeholder forces me to write code that
> mixes Python lexicon the new Java lexicon.
>
> My main worry is with Grails controllers where we need to define an action
> using `def` (or `Object`) as return type and define variables in the method
> body. At the moment we have the following options:
>
> *def* index() {
>     *def* myVar = ...
> }
>
> *def* index() {
>     *var* myVar = ...
> }
>
> *def* index() {
>     *Object* myVar = ...
> }
>
> *Object* index() {
>     *def* myVar = ...
> }
>
> *Object* index() {
>     *var* myVar = ...
> }
>
> *Object* index() {
>     *Object* myVar = ...
> }
>
> I would like to write controllers like this:
>
> *var* index() {
>     *var* myVar = ...
> }
>
> to keep the code clean and coherent with the Groovy documentation that
> states clearly that *"If you think of def and var as an alias of Object,
> you will understand in an instant."*
>
> Is this enough of an argument to ask for an implementation of `var` that is
> fully intrechangable with `def`?
>
> Please let me know what is your opinion on that,
> cheers,
> Gianluca
>
> Gianluca Sartori
> --
> Cell. +39 388 1026822
>

Reply via email to