You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@groovy.apache.org by MG <mg...@arscreat.com> on 2020/08/08 22:38:21 UTC

NV NameAndValue Macros

Hi Paul,

thank you for the link (https://github.com/apache/groovy/pull/1343 )

As far as I could see the NV macros you propose 
(https://github.com/apache/groovy/pull/1343/commits/0a3ba697511335a82ec7487998976aacdc8667de) 

all create "x0=${x0.foo()}, x1=${x1.foo()}, ..." GString|s, with foo in 
[toString, inspect, dump]:

NV ... "x0=$x0, x1=$x1, ..."-GString // toString() called on values; 
same as my NVS proposal
NVI  ... "x0=${x0.inspect()}, x1=${x1.inspect()}, ..."-GString // 
inspect called on values
NVD  ... "x0=${x0.dump()}, x1=${x1.dump()}, ..."-GString // dump called 
on values


However, the NameAndValue instance creation makes a) the concept very 
flexible, and b) elevates it beyond just logging (all examples dry-coded):

a) Examples:
println "path: ${NVL(x, y, z).join('/')}"  // arbitrary join
final weirdRegex = 
NVL(id,parentFiledReferenceIdentifier,name,humanReadableName).collect { 
"($it.name:$it.val)" }.join('|')  // arbitrary name-value-string + 
arbitrary join
final xml = 
"<properties>${NVL(id,parentFiledReferenceIdentifier,name,humanReadableName).collect 
{ "<$it.name>$it.val</$it.name>" }.join('')}</properties>" // another 
arbitrary name-value-string + arbitrary join (just a quick&dirty example 
- please stream properly escaped XML at all times :-) )

b) Examples: I use it for instance to define property collections in 
Pojo classes, which other methods then use to drive e.g. the output of 
the Pojo in a GUI table (or to create some SQL), e.g.:
List<NameAndValue> getImportantProperties() { NVL(id, name, children) }
List<NameAndValue<String>> getTextProperties() { NVL(firstName, 
lastName, description) }
String toXmlString() { "<foo ${importantProperties.collect { 
NameAndValue nv -> 
$/${xmlAttributeName(nv.name)}="${xmlAttributeVal(nv.val)}"/$ } }>insert 
text here...</foo>" }


The NameAndValue<T> class is of course indepent of the NV macro family, 
and can also be created explicitly, e.g. (assuming @Newify pattern):

final x = 100
final y = 123.456
final list = [ NameAndValue('first',x), NameAndValue('second',y) ] + 
NVL(pos.x, pos.y)

Keeping that use in mind, it could make sense to come up with a shorter 
class name for the NameAndValue class...


I would therefore suggest we support both:

// NameAndValue based
NV ... as my NVL before
NVP ... as NV, but first argument is treated as parameter for 
NameAndValue instance creation; e.g. NVP(NameAndValue.DUMP, a, b, c) // 
create NameAndValueExt instance, which will use dump method in its  
toString() method

// GString based
GV or NVS ... your NVI; GV = GStringed-variable(s)
GVI or NVSI ... your NVI
GVD or NVSD ... your NVD

Since "inspect" falls back to "toString", we could also just make GV/NVS 
use inspect, and only support GVD/NVSD besides that - then it would make 
sense to use "inspect" instead of "toString" in NameAndValue#toString 
also...

Cheers,
mg



On 07/08/2020 12:53, Paul King wrote:
> I created a starting set of NV, NVI and NVD macros similar (but 
> slightly different) to what mg has described previously. I see that as 
> a starting point for discussion.
>
> Something like 'returnIf' wouldn't be hard to add but I'd personally 
> prefer to explore enhancing our switch statement first since I think 
> that would cover many use cases where I'd be tempted to try 'returnIf'.
>
> Just on switch statements we have Java 13/14 enhanced switch we could 
> explore (switch expressions, yields/no breaks) and destructuring like 
> python's latest proposal[1] but obviously with our own syntax.
>
>
> Cheers, Paul.
> [1] https://www.python.org/dev/peps/pep-0622/
>
> On Wed, Aug 5, 2020 at 7:53 AM MG <mgbiz@arscreat.com 
> <ma...@arscreat.com>> wrote:
>
>     Hi Eric,
>
>     yea,  I got that, that's why I said "In that case a global setting
>     might /also/ be useful".
>
>     But I doubt that the majority of Groovy users out there who want
>     to quickly check if it is macros that make their code break in
>     Groovy 4 would know that to do so they just need to "add the macro
>     transform class to the disallowed list in CompilerConfiguration"; 
>     to be able to do so would mean one would a) need to know the macro
>     transform class exists and what its purpose and exact name is, b)
>     how the disallowed list in CompilerConfiguration works (that's the
>     easy part), as well as last but not least c) to be sure that doing
>     so will not just break part or all of Groovy... ;-)
>
>     I think you grossly underestimate the amount of Groovy (internal)
>     knowledge you have :-)
>
>     Cheers,
>     mg
>
>
>     On 04/08/2020 18:27, Milles, Eric (TR Technology) wrote:
>>
>>     In terms of globally disabling macro methods, you can just add
>>     the macro transform class to the disallowed list in
>>     CompilerConfiguration.  I think Paul is describing a mechanism
>>     where an individual macro method is taken out of service.
>>
>>     *From:* MG <mg...@arscreat.com> <ma...@arscreat.com>
>>     *Sent:* Tuesday, August 4, 2020 9:53 AM
>>     *To:* dev@groovy.apache.org <ma...@groovy.apache.org>; Paul
>>     King <pa...@asert.com.au> <ma...@asert.com.au>
>>     *Subject:* Re: [PROPOSAL]Support conditional return
>>
>>     Hi Paul,
>>
>>     thanks for clearing that up :-)
>>
>>     @unforeseen implications: In that case a global
>>     -Dgroovy.macro.enable=false
>>     might also be useful, to do a quick check if it is macros that
>>     are causing the problem (if we do not have that already).
>>
>>     Btw: Do we have a way to hide the macro definitions from e.g.
>>     IntelliJ Intellisense, and only show the stub implementation ? I
>>     use the NV macros* extensively by now in my code, and what I
>>     found is, that always having to select and import the stub class,
>>     and not the macro class is a (small) hassle.
>>
>>     Cheers,
>>     mg
>>
>>     *In practice it turns out the NV variety I use the most is NVL,
>>     which returns a list of NV instances, so is good for logging
>>     multiple variables. At some point in the future there will need
>>     to be a discussion what varieties we want to support; my
>>     suggestion would be:
>>     NV(x) ... single NameAndValue class instance
>>     NVL(x0,x1,...) ... list of NameAndValue instances
>>     NVS(x0,x1,...) ... "x0=$x0, x1=$x1, ..."-GString
>>     (we could also have NVS return an (efficiently built) String, and
>>     NVGS return the GString, but I am not sure whether that it is
>>     worth it)
>>
>>     On 04/08/2020 08:17, Paul King wrote:
>>
>>         Hi mg,
>>
>>         Just on supplying our own macros, we should do this for
>>         Groovy 4. We have been reluctant so far because we have been
>>         conservative about unforeseen implications. However, unless
>>         we start using them more widely, we aren't going to learn
>>         those implications.
>>
>>         I'd suggest having them (to start with) in their own optional
>>         incubating module (e.g. groovy-macro-samples) and we should
>>         come up with a way to disable any one of them, e.g.
>>         -Dgroovy.macro.enable.returnIf=false
>>         -Dgroovy.macro.enable.NV=true (or whatever).
>>
>>         Cheers, Paul.
>>
>>         On Wed, Jul 29, 2020 at 10:07 AM MG <mgbiz@arscreat.com
>>         <ma...@arscreat.com>> wrote:
>>
>>             I like that idea :-)
>>             (unless someone has a really convincing argument why not,
>>             100% for
>>             sticking with "it" instead of "_"/"$")
>>
>>             That would also allow for more flexibility with e.g.
>>             regards to the
>>             number of methods that are being evaluated, without
>>             getting into the
>>             problematic area of whether/ how to support this syntax-wise.
>>
>>             If there is nothing blocking this, the question is if
>>             Groovy should
>>             supply a basic version of such a macro (if Groovy is ever
>>             planning to
>>             supply macros of its own) ?
>>
>>             Cheers,
>>             mg
>>
>>
>>             On 28/07/2020 16:08, Milles, Eric (TR Technology) wrote:
>>             > If switch expression or pattern match macro is
>>             insufficient, could a macro be written to cover this
>>             "conditional return"?
>>             >
>>             > // "it" could easily be replaced by "_" or "$" as
>>             mentioned previously as options
>>             > def doSomething(int a) {
>>             >    returnIf(callB(), a > 6 && it > 10)
>>             >    returnIf(callC(), a > 5 && it > 20)
>>             >    returnIf(callD(), a > 4 && it > 30)
>>             > }
>>             >
>>             >    vs.
>>             >
>>             > def doSomething(int a) {
>>             >    return callB() if (a > 6 && _ > 10)
>>             >    return callC() if (a > 5 && _ > 20)
>>             >    return callD() if (a > 4 && _ > 30)
>>             > }
>>             >
>>             > -----Original Message-----
>>             > From: Daniel Sun <sunlan@apache.org
>>             <ma...@apache.org>>
>>             > Sent: Sunday, July 26, 2020 6:23 PM
>>             > To: dev@groovy.apache.org <ma...@groovy.apache.org>
>>             > Subject: Re: [PROPOSAL]Support conditional return
>>             >
>>             > Hi Sergei,
>>             >
>>             > ( Copied from twitter:
>>             https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Ftwitter.com%2Fbsideup%2Fstatus%2F1287477595643289601%3Fs%3D20&amp;data=02%7C01%7Ceric.milles%40thomsonreuters.com%7C411c66fda05844d7429908d831bacc9d%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637314025668554080&amp;sdata=vNa3dz0H%2BJAegS9Zb8HW2by0ueceqCKI6qDVFpBpbc4%3D&amp;reserved=0
>>             <https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Ftwitter.com%2Fbsideup%2Fstatus%2F1287477595643289601%3Fs%3D20&data=02%7C01%7Ceric.milles%40thomsonreuters.com%7Cd22419dbc45b40d96bf608d8388618f6%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637321496617678018&sdata=NBAn2FtRigVd8UFrZpPt7GdDLdI7kMVh%2BxTl2vNAtK0%3D&reserved=0>
>>             )
>>             >> But isn't it better with pattern matching? And what is
>>             "_" here?
>>             > The underscore represents the return value
>>             >
>>             >> Anyways:
>>             >> ```
>>             >> return match (_) {
>>             >>      case { it < 5 }: callC();
>>             >>      case { it > 10 }: callB();
>>             >>      case { it != null }: callA();
>>             >>      default: {
>>             >>          LOG.debug "returning callD"
>>             >>          return callD()
>>             >>      }
>>             >> }
>>             >> ```
>>             > pattern matching may cover some cases of Conditional
>>             Return, but it can not cover all. Actually the
>>             Conditional Return is more flexible, e.g.
>>             >
>>             > ```
>>             > def chooseMethod(String methodName, Object[] arguments)  {
>>             >     return doChooseMethod(methodName, arguments) if _
>>             != null
>>             >
>>             >     for (Class type : [Character.TYPE, Integer.TYPE]) {
>>             >        return doChooseMethod(methodName,
>>             adjustArguments(arguments.clone(), type)) if _ != null
>>             >     }
>>             >
>>             >     throw new GroovyRuntimeException("$methodName not
>>             found") } ```
>>             >
>>             > Even we could simplify the above code with `return?` if
>>             the condition is Groovy truth:
>>             > ```
>>             > def chooseMethod(String methodName, Object[] arguments)  {
>>             >     return? doChooseMethod(methodName, arguments)
>>             >
>>             >     for (Class type : [Character.TYPE, Integer.TYPE]) {
>>             >        return? doChooseMethod(methodName,
>>             adjustArguments(arguments.clone(), type))
>>             >     }
>>             >
>>             >     throw new GroovyRuntimeException("$methodName not
>>             found") } ```
>>             >
>>             > Cheers,
>>             > Daniel Sun
>>             > On 2020/07/26 18:23:41, Daniel Sun <sunlan@apache.org
>>             <ma...@apache.org>> wrote:
>>             >> Hi mg,
>>             >>
>>             >>> maybe you can give some real life code where you
>>             encounter this on a regular basis ?
>>             >> Let's think about the case about choosing method by
>>             method name and arguments:
>>             >>
>>             >> ```
>>             >> def chooseMethod(String methodName, Object[] arguments) {
>>             >>     def methodChosen = doChooseMethod(methodName,
>>             arguments)
>>             >>     if (null != methodChosen) return methodChosen
>>             >>
>>             >>     methodChosen = doChooseMethod(methodName,
>>             adjustArguments(arguments.clone(), Character.TYPE))
>>             >>     if (null != methodChosen) return methodChosen
>>             >>
>>             >>     methodChosen = doChooseMethod(methodName,
>>             adjustArguments(arguments.clone(), Integer.TYPE))
>>             >>     if (null != methodChosen) return methodChosen
>>             >>
>>             >>     throw new GroovyRuntimeException("$methodName not
>>             found") } ```
>>             >>
>>             >> The above code could be simplified as:
>>             >> ```
>>             >> def chooseMethod(String methodName, Object[] arguments) {
>>             >>     return? doChooseMethod(methodName, arguments)
>>             >>
>>             >>     return? doChooseMethod(methodName,
>>             >> adjustArguments(arguments.clone(), Character.TYPE))
>>             >>
>>             >>     return? doChooseMethod(methodName,
>>             >> adjustArguments(arguments.clone(), Integer.TYPE))
>>             >>
>>             >>     throw new GroovyRuntimeException("$methodName not
>>             found") } ```
>>             >>
>>             >> Or a general version:
>>             >> ```
>>             >> def chooseMethod(String methodName, Object[] arguments) {
>>             >>     return doChooseMethod(methodName, arguments) if _
>>             != null
>>             >>
>>             >>     return doChooseMethod(methodName,
>>             >> adjustArguments(arguments.clone(), Character.TYPE)) if
>>             _ != null
>>             >>
>>             >>     return doChooseMethod(methodName,
>>             >> adjustArguments(arguments.clone(), Integer.TYPE)) if _
>>             != null
>>             >>
>>             >>     throw new GroovyRuntimeException("$methodName not
>>             found") } ```
>>             >>
>>             >>
>>             >> Cheers,
>>             >> Daniel Sun
>>             >> On 2020/07/26 17:11:07, MG <mgbiz@arscreat.com
>>             <ma...@arscreat.com>> wrote:
>>             >>> Hi Daniel,
>>             >>>
>>             >>> currently I would be +/- 0 on this.
>>             >>>
>>             >>> Thoughts:
>>             >>>
>>             >>>   1. I feel I have written this before, but I myself
>>             do not encounter the
>>             >>>      situation where I would need to return the
>>             result of a method call
>>             >>>      only if it meets certain conditions when
>>             programming (maybe you can
>>             >>>      give some real life code where you encounter
>>             this on a regular basis ?).
>>             >>>   2. If I have more than one return, it typcially is
>>             an early out, which
>>             >>>      depends on the method's input parameters, not on
>>             the result of
>>             >>>      another method call.
>>             >>>   3. Since I do a lot of logging / log debugging, I
>>             typically assign the
>>             >>>      return value to a variable, so I can debug-log
>>             it before the one
>>             >>>      return of the method.
>>             >>>   4. In fact I have had to refactor code written by
>>             other people from
>>             >>>      multi-return methods to single return, to be
>>             able to track down bugs.
>>             >>>
>>             >>> So overall I am not sure one should enable people to
>>             make it easier
>>             >>> to write non-single-return methods ;-)
>>             >>>
>>             >>>
>>             >>> Purely syntax wise I would prefer
>>             >>> return?
>>             >>> for the simple case,
>>             >>>
>>             >>> and
>>             >>>
>>             >>> return <something> if <condition>
>>             >>> for the more complex one*.
>>             >>>
>>             >>> I find
>>             >>> return(<condition) <something>
>>             >>> confusing on what is actually returned.
>>             >>>
>>             >>> Cheers,
>>             >>> mg
>>             >>>
>>             >>> *Though I wonder if people would not then expect this
>>             >>> if-postfix-syntax to also work for e.g. assignments
>>             and method calls...
>>             >>>
>>             >>>
>>             >>> On 26/07/2020 16:15, Daniel Sun wrote:
>>             >>>> Hi Mario,
>>             >>>>
>>             >>>>       I think you have got the point of the proposal ;-)
>>             >>>>
>>             >>>>       If we prefer the verbose but clear syntax, I
>>             think we could introduce `_` to represent the return
>>             value for concise shape:
>>             >>>>
>>             >>>> ```
>>             >>>> return callB() if (_ != null && _ > 10)
>>             >>>>
>>             >>>> // The following code is like lambda expression,
>>             which is a bit
>>             >>>> more verbose return callB() if (result -> result !=
>>             null && result
>>             >>>>> 10) ```
>>             >>>>       Show the `_` usage in your example:
>>             >>>> ```
>>             >>>> def doSomething(int a) {
>>             >>>>     return callB() if (a > 6 && _ > 10)
>>             >>>>     return callC() if (a > 5 && _ > 20)
>>             >>>>     return callD() if (a > 4 && _ > 30) } ```
>>             >>>>
>>             >>>> ```
>>             >>>> // optional parentheses
>>             >>>> def doSomething(int a) {
>>             >>>>     return callB() if a > 6 && _ > 10
>>             >>>>     return callC() if a > 5 && _ > 20
>>             >>>>     return callD() if a > 4 && _ > 30 } ```
>>             >>>>
>>             >>>> ```
>>             >>>> // one more example
>>             >>>> def doSomething(int a) {
>>             >>>>     return callB()         if a > 6 && _ > 10
>>             >>>>     return callC() + callD() if a > 5 && _ > 50 } ```
>>             >>>>
>>             >>>>       BTW, the parentheses behind `if` could be
>>             optional.
>>             >>>>
>>             >>>> Cheers,
>>             >>>> Daniel Sun
>>             >>>> On 2020/07/26 11:29:39, Mario Garcia
>>             <mario.ggar@gmail.com <ma...@gmail.com>> wrote:
>>             >>>>> Hi all:
>>             >>>>>
>>             >>>>> Very interesting topic.
>>             >>>>>
>>             >>>>> The first idea sprang to mind was the PMD rule in
>>             Java saying you
>>             >>>>> should have more than one exit point in your methods (
>>             >>>>>
>>             https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpmd.github.io%2Flatest%2Fpmd_rules_java_codestyle.html%23onlyonereturn&amp;data=02%7C01%7Ceric.milles%40thomsonreuters.com%7C411c66fda05844d7429908d831bacc9d%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637314025668554080&amp;sdata=5m%2B5ejCWEicseaUp5wK0UDjHwpfMFht5ptjglZ9IWS4%3D&amp;reserved=0
>>             <https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpmd.github.io%2Flatest%2Fpmd_rules_java_codestyle.html%23onlyonereturn&data=02%7C01%7Ceric.milles%40thomsonreuters.com%7Cd22419dbc45b40d96bf608d8388618f6%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637321496617688010&sdata=vHsd4PrZTGJxhfAvtPxKLEfAvxiidhOAVvqFthIDHTU%3D&reserved=0>).
>>             >>>>> But the reality is that sometimes (more often than
>>             not) we are
>>             >>>>> forced to break that rule. In fact sometimes we
>>             could even argue
>>             >>>>> that breaking that rule makes the code clearer (e.g
>>             >>>>>
>>             https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2
>>             <https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%252>
>>             >>>>>
>>             Fmedium.com%2Fncr-edinburgh%2Fearly-exit-c86d5f0698ba&amp;data=02
>>             >>>>> %7C01%7Ceric.milles%40thomsonreuters.com
>>             <https://nam02.safelinks.protection.outlook.com/?url=http%3A%2F%2F40thomsonreuters.com%2F&data=02%7C01%7Ceric.milles%40thomsonreuters.com%7Cd22419dbc45b40d96bf608d8388618f6%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637321496617688010&sdata=dVEeA8WhNRImv11c7OIRUDcIyrjq58kF0o%2F5R%2BK6WlU%3D&reserved=0>%7C411c66fda05844d7429908
>>             >>>>>
>>             d831bacc9d%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637314025
>>             >>>>>
>>             668554080&amp;sdata=q8VrgoQDeH85232oyMgQT8WwljNqoUjIc4cS7GGqH5I%3
>>             >>>>> D&amp;reserved=0)
>>             >>>>>
>>             >>>>> Although my initial reaction was to be against the
>>             proposal,
>>             >>>>> however after doing some coding, I've found that
>>             neither elvis
>>             >>>>> nor ternary operators makes it easier nor clearer.
>>             Here's why I think so. Taking Daniel's example:
>>             >>>>>
>>             >>>>> ```
>>             >>>>> def m() {
>>             >>>>>      def a = callA()
>>             >>>>>      if (null != a) return a
>>             >>>>>
>>             >>>>>      def b = callB()
>>             >>>>>      if (b > 10) return b
>>             >>>>>
>>             >>>>>      def c = callC()
>>             >>>>>      if (null != c && c < 10) return c
>>             >>>>>
>>             >>>>> LOGGER.debug('the default value will be returned')
>>             >>>>>
>>             >>>>>      return defaultValue
>>             >>>>> }
>>             >>>>> ```
>>             >>>>> The shortest elvis operator approach I could think
>>             of was:
>>             >>>>> ```
>>             >>>>> def m2() {
>>             >>>>>      return callA()
>>             >>>>>          ?: callB().with { it > 10 ? it : null }
>>             >>>>>          ?: callC().with { null != it && it <10 ?
>>             it : null } }
>>             >>>>> ```
>>             >>>>>
>>             >>>>> which to be honest, is ugly to read, whereas
>>             Daniel's proposal is just:
>>             >>>>>
>>             >>>>> ```
>>             >>>>> def m() {
>>             >>>>>      return? callA()
>>             >>>>>      return(r -> r > 10) callB()
>>             >>>>>      return(r -> null != r && r < 10) callC()
>>             >>>>>      return defaultValue
>>             >>>>> }
>>             >>>>> ```
>>             >>>>>
>>             >>>>> Once said that, I would say this conditional return
>>             could be
>>             >>>>> useful only when there are more than two exit
>>             points, otherwise
>>             >>>>> ternary or elvis operators may be good enough.
>>             >>>>>
>>             >>>>> So, bottom line, I kinda agree to add conditional
>>             return, but I'm
>>             >>>>> not sure about the final syntax:
>>             >>>>>
>>             >>>>> ```
>>             >>>>> return(r -> r > 10) callB()
>>             >>>>> return callB() [r -> r > 10]
>>             >>>>> return callB() if (r -> r > 10)
>>             >>>>> ```
>>             >>>>>
>>             >>>>> Between the three I the one that I like the most is
>>             the third one:
>>             >>>>>
>>             >>>>> ```
>>             >>>>> return callB() if (r -> r > 10)
>>             >>>>> ```
>>             >>>>>
>>             >>>>> You can read it in plain english as "return this if
>>             this
>>             >>>>> condition happens".
>>             >>>>>
>>             >>>>> Apart from Daniel's use case, using this option
>>             could open the
>>             >>>>> possibility to use, not only a closure or lambda
>>             expression, but
>>             >>>>> also a plain expression. A nice side effect could
>>             be that
>>             >>>>> something like the following code:
>>             >>>>>
>>             >>>>> ```
>>             >>>>> def doSomething(int a) {
>>             >>>>>     return callB() if a > 6
>>             >>>>>     return callC() if a > 5
>>             >>>>>     return callD() if a > 4
>>             >>>>> }
>>             >>>>> ```
>>             >>>>>
>>             >>>>> turns out to be a shorter (and in my opinion
>>             nicest) way of
>>             >>>>> switch case (when you want every branch to return
>>             something):
>>             >>>>>
>>             >>>>> ```
>>             >>>>> def doSomething(int a) {
>>             >>>>>     switch (a) {
>>             >>>>>        case { it > 6 }: return callB()
>>             >>>>>        case { it > 5 }: return callC()
>>             >>>>>        case { it > 4 }: return callD()
>>             >>>>>     }
>>             >>>>> }
>>             >>>>> ```
>>             >>>>>
>>             >>>>> Well, bottom line, I'm +1 Daniel's proposal because
>>             I've seen
>>             >>>>> some cases where this conditional return could make
>>             the code clearer.
>>             >>>>>
>>             >>>>> Cheers
>>             >>>>> Mario
>>             >>>>>
>>             >>>>> El sáb., 25 jul. 2020 a las 23:55, Paolo Di Tommaso (<
>>             >>>>> paolo.ditommaso@gmail.com
>>             <ma...@gmail.com>>) escribió:
>>             >>>>>
>>             >>>>>> It's not much easier a conditional expression (or
>>             even the elvis
>>             >>>>>> operator)?
>>             >>>>>>
>>             >>>>>> ```
>>             >>>>>> def m() {
>>             >>>>>>       def r = callSomeMethod()
>>             >>>>>>       return r != null ? r : theDefaultResult } ```
>>             >>>>>>
>>             >>>>>>
>>             >>>>>> On Sat, Jul 25, 2020 at 8:56 PM Daniel Sun
>>             <sunlan@apache.org <ma...@apache.org>> wrote:
>>             >>>>>>
>>             >>>>>>> Hi all,
>>             >>>>>>>
>>             >>>>>>>        We always have to check the returning
>>             value, if it match
>>             >>>>>>> some condition, return it. How about simplifying
>>             it? Let's see an example:
>>             >>>>>>>
>>             >>>>>>> ```
>>             >>>>>>> def m() {
>>             >>>>>>>       def r = callSomeMethod()
>>             >>>>>>>       if (null != r) return r
>>             >>>>>>>
>>             >>>>>>>       return theDefaultResult
>>             >>>>>>> }
>>             >>>>>>> ```
>>             >>>>>>>
>>             >>>>>>> How about simplifying the above code as follows:
>>             >>>>>>> ```
>>             >>>>>>> def m() {
>>             >>>>>>>       return? callSomeMethod()
>>             >>>>>>>       return theDefaultResult
>>             >>>>>>> }
>>             >>>>>>> ```
>>             >>>>>>>
>>             >>>>>>> Futhermore, we could make the conditional return
>>             more general:
>>             >>>>>>> ```
>>             >>>>>>> def m() {
>>             >>>>>>>  return(r -> r != null) callSomeMethod() // we
>>             could do
>>             >>>>>>> more checking, e.g. r > 10
>>             >>>>>>>       return theDefaultResult
>>             >>>>>>> }
>>             >>>>>>> ```
>>             >>>>>>>
>>             >>>>>>>       Any thoughts?
>>             >>>>>>>
>>             >>>>>>> Cheers,
>>             >>>>>>> Daniel Sun
>>             >>>>>>>
>>             >>>
>>
>