Hi Paul,

thanks for your reply. If I had known you were gonna hit back with so much detail, I would have gone with splitting my mail into multiple parts (but didn't want to spam the mailing list) ;-)
I will read up on your links and reply in smaller chunks...

Cheers,
Markus


On 21.08.2017 04:30, Paul King wrote:
Hi Markus,

Thanks for your suggestions. Some neat ideas in your suggestions! Just a general comment to start off with...

With language design, it's often the details which are important, so I'd suggest rather than going straight from this email to a bunch of PRs, you'd create separate Jira issues for those items you want to pursue and flesh out the design a little more - it's often the dealing with backwards compatibility and handling error situations that take up more of the design time than the actual feature itself. Having said that, please don't be put off with the extra work. We usually follow the same process ourselves and find the extra discipline helps all round. For simple non-controversial enhancements, not much detail might be needed but in other cases, there might be lots of details that need to be handled that might not be apparent at first - plus a Jira issue is a good place for us to suggest hints on how to get started.

Some more comments inline below ...

Cheers, Paul.

On Mon, Aug 21, 2017 at 6:25 AM, MG <mg...@arscreat.com <mailto:mg...@arscreat.com>> wrote:

    Hi,

    before I create change requests, I wanted to ask for some quick
    feedback on the following potential new Groovy features (I
    apologize beforehand, if any of these are already covered in some
    way, and I missed it, or if they have been discussed before, etc -
    just throwing ideas that I find useful out there :-) ):

     1. Named Parameters: I already posted that feature request here.
        The most plain vanilla support (support the <name>:<value>,
        <name>:<value>, ... syntax to give named ctor/method args)
        would already cover 99% of applications here, I think. The
        imho most problematic feedback was external libraries without
        debug information - my question would be how frequently such
        libraries occur in practice (I personally have never pressed
        Ctrl+B in IntelliJ and not gotten a method decompile result
        with parameter names) ?

It is certainly worth fleshing this out a little more. Such support has been considered in the past [1,2] but that was prior to JEP118[3,4] being finalized and we decided to wait. Some of the backwards compatibility issues mentioned in that thread still remain and we'd need to spell out what we are planning in that regard (that affects what version this might be merged into).  I'll also note that there are some tricks that IDEs might use (looking at source code, javadoc etc.) that we would not likely pursue. There are also some pre java8 tricks that can be used [5,6,7] but I think we would more likely want to pursue the JEP118 approach - though do feel free to experiment if you think those approaches might be useful - we'd need to weigh up what additional libraries that might required to be available for basic compilation. I have less optimism about whether JEP118 metadata information will be available anytime soon - doesn't mean we shouldn't provide support in the meantime for the situations where it does exist. I did a sample size of 1 by downloading the latest Guava and it wasn't available in that library - also the Java libraries themselves didn't have that information last time I checked. Also, there is an old issue that could be useful that would work for constructors even on old JDK versions using a JavaBean annotation[8] though again I don't think widely used. Also, we'd need to understand if there are any impacts on Groovy's mixed Map/positional notation and whether true optional arguments support would be included[9].

[1] https://groups.google.com/forum/#!topic/groovy-user/8MuO1TTw-aQ <https://groups.google.com/forum/#%21topic/groovy-user/8MuO1TTw-aQ> [2] https://github.com/pniederw/groovy-extensions <https://github.com/pniederw/groovy-extensions>
[3] http://openjdk.java.net/jeps/118 <http://openjdk.java.net/jeps/118>
[4] https://bugs.openjdk.java.net/secure/attachment/11079/8misc.pdf <https://bugs.openjdk.java.net/secure/attachment/11079/8misc.pdf> [5] https://github.com/paul-hammant/paranamer <https://github.com/paul-hammant/paranamer> [6] http://docs.spring.io/spring/docs/3.0.x/javadoc-api/org/springframework/core/LocalVariableTableParameterNameDiscoverer.html <http://docs.spring.io/spring/docs/3.0.x/javadoc-api/org/springframework/core/LocalVariableTableParameterNameDiscoverer.html> [7] http://docs.spring.io/spring/docs/3.0.x/javadoc-api/org/springframework/core/ParameterNameDiscoverer.html <http://docs.spring.io/spring/docs/3.0.x/javadoc-api/org/springframework/core/ParameterNameDiscoverer.html> [8] https://issues.apache.org/jira/browse/GROOVY-3661 <https://issues.apache.org/jira/browse/GROOVY-3661> [9] https://issues.apache.org/jira/browse/GROOVY-3520 <https://issues.apache.org/jira/browse/GROOVY-3520>

     1. Support making all method/ctor parameters final by default
        through "autofinal" Groovy compiler flag:
        Foo(int x, String s) { // final keyword is auto added to all
        parameters, if compiler flag is set, i.e. this automatically
        becomes Foo(final int x, final String s)
        this.x = x; this.s
        }
        Rationale: Even if Groovy source samples use def instead of
        final a lot, parameters (and variables) are, according to my
        experience, most of the time actually final in practice (In
        the few cases where one needs to modify a parameter, it can
        immediately be assigned to a variable). This feature would
        reduce the source code clutter that comes from the need to
        qualify parameters as final all the time.

You can already leave off the "clutter" and apply a CodeNarc rule[1] to detect "bad" style. Also, it would be an easy task to create an @AutoFinal local transform which could then be automatically applied using a compiler customizer. I think going further with a dedicated compiler flag would be a later step if such a local transform became extremely popular.

[1] http://codenarc.sourceforge.net/codenarc-rules-convention.html#ParameterReassignment <http://codenarc.sourceforge.net/codenarc-rules-convention.html#ParameterReassignment>

     1. Deduce the type of final fields from their assigned value:
     2. class Foo {
        final device = new PrinterDevice(...) // device field will
        have type PrinterDevice instead of Object when reflection is
        used on class Foo
        }
        Rationale: While IntelliJ does a good job at deducing the type
        of final fields, it would still be better if the Groovy
        language itself would use the more specialized type here, for
        e.g. reflection purposes

With @Typechecked or @CompileStatic type inferencing is going to be in play. During debugging the runtime type is going to be available. What "reflective purposes" did you have in mind?

     1. Introduce a "var" (o.s.) keyword that allows deduction of type
        through assignment:
        var device = new PrinterDevice(...) // device variable will
        have type PrinterDevice without the need to explictely state that
        Rationale: This is a well known feature of other languages,
        that reduces the need to explictely define the type of variables.

How is this different to the current type inferencing?

     1. Always allow ctor calls without new keyword:
        final foo = Foo("abc") // creates a new Foo instance by
        calling Foo class ctor with signature
        Rationale: new keyword was necessary in C++ to distinguish
        heap vs stack variable allocation. No such need exists in
        Groovy, so the keyword just clutters the source code. Naming
        convention of method names being always lowercase prevents
        name clashes with methods.

 A partial solution to this is available via @Newify. As far as I know, @Newify hasn't been super popular, so we'd need to think carefully about introducing this.

     1. "Variable plus Name" support: One of the most useful macros I
        used in C++ was NV(x), where I passed a variable, and created
        a NamedVariable instance, which was automatically passed the
        name and the value of the variable (through simple macro
        stringify). I would love to see something similar in Groovy.
        Rationale: Most important application is DRY creation of debug
        output, e.g.:  println NV(longVariableName)  // equivalent
        result to println "longVariableName=$longVariableName" avoding
        the potential classical copy & paste error
        "longVariableName=$longrVariableName"

Sounds like a possible candidate for using Macros?

     1. Support break/continue to work as if a closure was a block
        construct, e.g. through an annotation on the Closure parameter:
        sqe.forEachRow("select * from PERSON") { final row ->
        if(row.TAG == 0) { continue } // Move to next iteration in
        forEachRow iteration over PERSON table
        if(row.TAG == 1) { break } // Return form closure & return
        from forEachRow (effectively stopping to iterate over PERSON
        table rows, continuing after the method call)
        }
        Rationale: Groovy's support for giving a Closure as the last
        argument outside of the parameter brackets is one of its most
        neat features. Supporting break/continue with expected (least
        surprise) semantics inside of such closures, would make this
        feature complete.
        (Note: I have implemented support for a "BreakLoopException"
        in my code, so that the closure body can signal a break to
        e.g. forEachRow, but that is still quite an akward solution,
        that breaks the illusion that forEachRow works like a regular
        for-each statement)

Non-local transfers (break/continue/non-local returns) have been discussed before[1] but perhaps worth revisiting now that Scala supports the non-local return approach using Exceptions[2] and Kotlin has labelled returns in lambda functions[3]. The main issue to keep in mind would be backwards compatibility/breaking changes.

[1] http://blackdragsview.blogspot.com.au/2006/09/non-local-transfers-in-groovy-90.html <http://blackdragsview.blogspot.com.au/2006/09/non-local-transfers-in-groovy-90.html> [2] http://dev.bizo.com/2010/01/scala-supports-non-local-returns.html <http://dev.bizo.com/2010/01/scala-supports-non-local-returns.html> [3] https://kotlinlang.org/docs/reference/returns.html <https://kotlinlang.org/docs/reference/returns.html>

     1. CompileStatic byte code call compatibility with Java: I have
        included this, since I saw it on the mailing list here, and I
        always tell everyone that Groovy is basically a drop in
        replacement for Java, which in this case, if obfuscation is
        part of the game, does not seem to be the case (in addition my
        son has also started to mod Minecraft a bit, and I wanted to
        use this to introduce him to Groovy - after he has suffered
        through a bit of Java ;-) ).

There are definitely edge cases where @CompileStatic falls back to dynamic calls which we want to improve.

    mg




Reply via email to