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> 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
[2] https://github.com/pniederw/groovy-extensions
[3] http://openjdk.java.net/jeps/118
[4] https://bugs.openjdk.java.net/secure/attachment/11079/8misc.pdf
[5] https://github.com/paul-hammant/paranamer
[6] 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
[8] https://issues.apache.org/jira/browse/GROOVY-3661
[9] 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

>
>    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
[2] http://dev.bizo.com/2010/01/scala-supports-non-local-returns.html
[3] 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