Hi guys,

yup, the current choice of support for var in Groovy is def a problem in my lexicon, ah, book... ;-)

var was always intended for the case of "type inference from an assignment", the way it is used in Java, and imho that is also what people coming fom other languages would expect. However, because it was much easier to implement and because of the forever-argument of "one cannot always a 100% deduce the RHS type of a expression the user might be expecting", the path taken was to basically make it so var is the same as def, i.e. the Object type, just with less applicability than def, since, afair, we wanted to at least keep the door open for supporting type inference through var in the future. To now make it a full-on alias for def would more or less prohibit that.

Apart from that, I agree with Eric that var goo() also looks semantically wrong.

I also think the "Python vs Java lexicon" argument is quite weak, since def is not Python specific, and has been in Groovy since the beginning...

*TLDR:*
If you want the semantics of def in Groovy, you should use def everywhere (as Groovy developers have done for decades), and not use var, which at this point only exists to satsify Groovy's goal of maximum Java syntax compatibility where possible, and in a possible future extension could support type inference, which is probably not what you want/expect when using var as a synonym for def :-)

Cheers,
mg


On 21/11/2024 22:04, Milles, Eric (TR Technology) via dev wrote:
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