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 <mg...@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.g...@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://pmd.github.io/latest/pmd_rules_java_codestyle.html#onlyonereturn). > >> 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://medium.com/ncr-edinburgh/early-exit-c86d5f0698ba) > >> > >> 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.ditomm...@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 <sun...@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 > >>>> > >