Re: [PROPOSAL]Support conditional return

2020-08-07 Thread Paul King
https://github.com/apache/groovy/pull/1343

On Sat, Aug 8, 2020 at 3:25 AM MG  wrote:

> GitHub link ?-)
>
> 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.
>
>
>
>
>
>


Re: [PROPOSAL]Support conditional return

2020-08-07 Thread MG

GitHub link ?-)

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.








Re: [PROPOSAL]Support conditional return

2020-08-07 Thread Paul King
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  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  
> *Sent:* Tuesday, August 4, 2020 9:53 AM
> *To:* dev@groovy.apache.org; Paul King 
> 
> *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  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" coul

Re: [PROPOSAL]Support conditional return

2020-08-04 Thread MG

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 
*Sent:* Tuesday, August 4, 2020 9:53 AM
*To:* dev@groovy.apache.org; Paul King 
*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 mailto:mg...@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 mailto:sun...@apache.org>>
> Sent: Sunday, July 26, 2020 6:23 PM
> To: dev@groovy.apache.org <mailto:dev@groovy.apache.org>
> Subject: Re: [PROPOSAL]Support conditio

RE: [PROPOSAL]Support conditional return

2020-08-04 Thread Milles, Eric (TR Technology)
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 
Sent: Tuesday, August 4, 2020 9:53 AM
To: dev@groovy.apache.org; Paul King 
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 
mailto:mg...@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 mailto:sun...@apache.org>>
> Sent: Sunday, July 26, 2020 6:23 PM
> To: dev@groovy.apache.org<mailto:dev@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%3D20data=02%7C01%7Ceric.milles%40thomsonreuters.com%7C411c66fda05844d7429908d831bacc9d%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637314025668554080sdata=vNa3dz0H%2BJAegS9Zb8HW2by0ueceqCKI6qDVFpBpbc4%3Dreserved=0<https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Ftwitter.com%2Fbsideup%2Fstatus%2F1287477595643289601%3Fs%3D20=02%7C01%7Ceric.milles%40thomsonreuters.com%7Cd22419dbc45b40d96bf608d8388618f6%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637321496617678018=NBAn2FtRigVd8UFrZpPt7GdDLdI7kMVh%2BxTl2vNAtK0%3D=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 Condit

Re: [PROPOSAL]Support conditional return

2020-08-04 Thread MG

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 <mailto:mg...@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 mailto:sun...@apache.org>>
> Sent: Sunday, July 26, 2020 6:23 PM
> To: dev@groovy.apache.org <mailto:dev@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%3D20data=02%7C01%7Ceric.milles%40thomsonreuters.com%7C411c66fda05844d7429908d831bacc9d%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637314025668554080sdata=vNa3dz0H%2BJAegS9Zb8HW2by0ueceqCKI6qDVFpBpbc4%3Dreserved=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
>     }
>
>

Re: [PROPOSAL]Support conditional return

2020-08-04 Thread Paul King
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  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 
> > Sent: Sunday, July 26, 2020 6:23 PM
> > To: dev@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%3D20data=02%7C01%7Ceric.milles%40thomsonreuters.com%7C411c66fda05844d7429908d831bacc9d%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637314025668554080sdata=vNa3dz0H%2BJAegS9Zb8HW2by0ueceqCKI6qDVFpBpbc4%3Dreserved=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  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) ret

Re: [PROPOSAL]Support conditional return

2020-07-30 Thread Jochen Theodorou

On 30.07.20 18:08, MG wrote:

1. Hiding a semantic "if" inside a "for"-loop syntax is not good, in my
book - in C++ I would have introduced a "returnIf"-macro to make the
intention clear in that case... ;-)

2. I was also thinking along the same line, but more like:

if(it = goo(); a>6 && it>10) { return it }

How does the return know what to return in your example, btw... ?-)

3. Would the "it" variable in the ClosureList move from term to term,
i.e. it would always reference the last term before the current one, or
always refernce the first ?


the idea in the original ClosureList was that each element of the list
is a Closure, the only difference being that they share the same
variable scope. So (def it = goo(); a>6 && it>10; return it) would
absolutely allow for the declaration of a variable it, to be used in the
condition and the return. The method taking the ClosureList, here "if"
determines order and meaning of the elements..

What of course does not work is the return ;) Sorry, forgot that.




Cheers,
mg

PS: The difference between
returnIf (goo(); a>6 && it>10)
and
returnIf (goo(), a>6 && it>10)
is of course miniscule, and maybe the second variety might actually be
less confusing... (?)


yeah, I think if we go for that returnIf, we really should go for the
semicolon

 bye Jochen



Re: [PROPOSAL]Support conditional return

2020-07-30 Thread MG
eturn"?

// "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 
Sent: Sunday, July 26, 2020 6:23 PM
To: dev@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=02%7C01%7Ceric.milles%40thomsonreuters.com%7C411c66fda05844d7429908d831bacc9d%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637314025668554080=vNa3dz0H%2BJAegS9Zb8HW2by0ueceqCKI6qDVFpBpbc4%3D=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  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  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 ;-)

Re: [PROPOSAL]Support conditional return

2020-07-30 Thread MG
In that case I would go back to Eric's suggestion, if we still feel we 
need a macro solution... :-)


On 30/07/2020 01:10, Daniel Sun wrote:

Hi mg,

  I like your idea, but it's hard for IDE to infer the type of `it` during 
we coding.

```
returnIf(a > 6 && it > 10) { goo() }
```

Cheers,
Daniel Sun
On 2020/07/29 20:28:13, MG  wrote:

Hi Daniel,

good idea also :-)

If the arguments are in this order however, it looks like a regular if
with its execution block to me...
Having the method call as the second argument would express more
intuitively what is happening - so maybe one should flip the order of
the arguments, and use:

returnIf(a > 6 && it > 10) { goo() }

Cheers,
mg


PS: If it = callB() were to be executed lazily, and no "it" argument
existed inside the condition, it would not be evaluated at all if
condition evaluates to false, making

returnIf() { goo() }

equivalent to

if() { return goo() }



On 29/07/2020 05:18, Daniel Sun wrote:

Hi Eric,

 I like your idea too ;-)

 We could use closure to express the condition at the tailing of method 
call:
```
def doSomething(int a) {
returnIf(callB()) { a > 6 && it > 10 }
returnIf(callC()) { a > 5 && it > 20 }
returnIf(callD()) { a > 4 && it > 30 }
}
```

Cheers,
Daniel Sun
On 2020/07/28 14:08:45, "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 
Sent: Sunday, July 26, 2020 6:23 PM
To: dev@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=02%7C01%7Ceric.milles%40thomsonreuters.com%7C411c66fda05844d7429908d831bacc9d%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637314025668554080=vNa3dz0H%2BJAegS9Zb8HW2by0ueceqCKI6qDVFpBpbc4%3D=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  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,
adjustArgu

Re: [PROPOSAL]Support conditional return

2020-07-30 Thread MG
1. Hiding a semantic "if" inside a "for"-loop syntax is not good, in my 
book - in C++ I would have introduced a "returnIf"-macro to make the 
intention clear in that case... ;-)


2. I was also thinking along the same line, but more like:

if(it = goo(); a>6 && it>10) { return it }

How does the return know what to return in your example, btw... ?-)

3. Would the "it" variable in the ClosureList move from term to term, 
i.e. it would always reference the last term before the current one, or 
always refernce the first ?


Cheers,
mg

PS: The difference between
returnIf (goo(); a>6 && it>10)
and
returnIf (goo(), a>6 && it>10)
is of course miniscule, and maybe the second variety might actually be 
less confusing... (?)




On 30/07/2020 10:26, Jochen Theodorou wrote:

On 30.07.20 01:10, Daniel Sun wrote:

Hi mg,

  I like your idea, but it's hard for IDE to infer the type of 
`it` during we coding.


```
returnIf(a > 6 && it > 10) { goo() }
```



long time ago I made the suggestion of a ClosureList based on the
classic for: "(" expr (";" expr)+ ")". It  got shot down very much for
being so ugly, but using that, we would get this:

```
returnIf (goo(); a>6 && it>10)
```

of course going crazy we could move this further:

```
for (goo(); a>6 && it>10;) {return}
```

or


```
for (goo(); a>6 && it>10; return)
```

bye Jochen




Re: [PROPOSAL]Support conditional return

2020-07-30 Thread MG

Hi Daniil,

1. without "??:", that only works for the case where Groovy-truth is
   applicable for the return value of doChooseMethod
2. I find the [null, Character.TYPE, Integer.TYPE]-iteration idea
   clearer / more DRY here irrespective of that :-)
3. Why _is_ "throw" not considered an expression in Groovy, and should
   we remedy that... G-)
4. Who is Johan ?-)

Cheers,
mg

On 30/07/2020 16:03, Daniil Ovchinnikov wrote:

I agree with Johan here, I’d even go ahead and write something like:
```
def chooseMethod(String methodName, Object[] arguments) {
final methodChosen = doChooseMethod(methodName, arguments)
?: doChooseMethod(methodName, adjustArguments(arguments.clone(), 
Character.TYPE))
?: doChooseMethod(methodName, adjustArguments(arguments.clone(), 
Integer.TYPE))
if (null != methodChosen) return methodChosen
throw new GroovyRuntimeException("$methodName not found")
}
```
If the language would consider ‘throw' an expression, then:
```
def chooseMethod(String methodName, Object[] arguments) {
return doChooseMethod(methodName, arguments)
?: doChooseMethod(methodName, adjustArguments(arguments.clone(), 
Character.TYPE))
?: doChooseMethod(methodName, adjustArguments(arguments.clone(), 
Integer.TYPE))
?: throw new GroovyRuntimeException("$methodName not found")
}
```

-1 from me overall.
—

Daniil Ovchinnikov
JetBrains


On 27 Jul 2020, at 07:00, Jochen Theodorou  wrote:

On 26.07.20 20:23, Daniel Sun 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")
}
```

now that I would now maybe write like this:


def chooseMethod(String methodName, Object[] arguments) {
def methodChosen = doChooseMethod(methodName, arguments)
methodChosen ?: doChooseMethod(methodName, 
adjustArguments(arguments.clone(), Character.TYPE))
methodChosen ?: doChooseMethod(methodName, 
adjustArguments(arguments.clone(), Integer.TYPE))
if (null != methodChosen) return methodChosen

throw new GroovyRuntimeException("$methodName not found")
}


compared to


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")
}
```

bye Jochen




RE: [PROPOSAL]Support conditional return

2020-07-30 Thread Milles, Eric (TR Technology)
> for (goo(); a>6 && it>10;) {return}

Actually my first take on the macro implementation was to create a for 
statement because it provides a scope for a temp variable and supports a 
statement.  Then I discovered that macro methods must return an expression...

-Original Message-
From: Jochen Theodorou  
Sent: Thursday, July 30, 2020 3:27 AM
To: dev@groovy.apache.org
Subject: Re: [PROPOSAL]Support conditional return

On 30.07.20 01:10, Daniel Sun wrote:
> Hi mg,
>
>   I like your idea, but it's hard for IDE to infer the type of `it` 
> during we coding.
>
> ```
> returnIf(a > 6 && it > 10) { goo() }
> ```


long time ago I made the suggestion of a ClosureList based on the classic for: 
"(" expr (";" expr)+ ")". It  got shot down very much for being so ugly, but 
using that, we would get this:

```
retunIf (goo(); a>6 && it>10)
```

of course going crazy we could move this further:

```
for (goo(); a>6 && it>10;) {return}
```

or


```
for (goo(); a>6 && it>10; return)
```

bye Jochen


Re: [PROPOSAL]Support conditional return

2020-07-30 Thread Daniil Ovchinnikov
I agree with Johan here, I’d even go ahead and write something like:
```
def chooseMethod(String methodName, Object[] arguments) {
   final methodChosen = doChooseMethod(methodName, arguments)
   ?: doChooseMethod(methodName, adjustArguments(arguments.clone(), 
Character.TYPE))
   ?: doChooseMethod(methodName, adjustArguments(arguments.clone(), 
Integer.TYPE))
   if (null != methodChosen) return methodChosen
   throw new GroovyRuntimeException("$methodName not found")
}
```
If the language would consider ‘throw' an expression, then:
```
def chooseMethod(String methodName, Object[] arguments) {
   return doChooseMethod(methodName, arguments)
   ?: doChooseMethod(methodName, adjustArguments(arguments.clone(), 
Character.TYPE))
   ?: doChooseMethod(methodName, adjustArguments(arguments.clone(), 
Integer.TYPE))
   ?: throw new GroovyRuntimeException("$methodName not found")
}
```

-1 from me overall.
—

Daniil Ovchinnikov
JetBrains

> On 27 Jul 2020, at 07:00, Jochen Theodorou  wrote:
> 
> On 26.07.20 20:23, Daniel Sun 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")
>> }
>> ```
> 
> now that I would now maybe write like this:
> 
>>> def chooseMethod(String methodName, Object[] arguments) {
>>>def methodChosen = doChooseMethod(methodName, arguments)
>>>methodChosen ?: doChooseMethod(methodName, 
>>> adjustArguments(arguments.clone(), Character.TYPE))
>>>methodChosen ?: doChooseMethod(methodName, 
>>> adjustArguments(arguments.clone(), Integer.TYPE))
>>>if (null != methodChosen) return methodChosen
>>> 
>>>throw new GroovyRuntimeException("$methodName not found")
>>> }
> 
> 
> compared to
> 
>> 
>> 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")
>> }
>> ```
> 
> bye Jochen



Re: [PROPOSAL]Support conditional return

2020-07-30 Thread Jochen Theodorou

On 30.07.20 01:10, Daniel Sun wrote:

Hi mg,

  I like your idea, but it's hard for IDE to infer the type of `it` during 
we coding.

```
returnIf(a > 6 && it > 10) { goo() }
```



long time ago I made the suggestion of a ClosureList based on the
classic for: "(" expr (";" expr)+ ")". It  got shot down very much for
being so ugly, but using that, we would get this:

```
retunIf (goo(); a>6 && it>10)
```

of course going crazy we could move this further:

```
for (goo(); a>6 && it>10;) {return}
```

or


```
for (goo(); a>6 && it>10; return)
```

bye Jochen


Re: [PROPOSAL]Support conditional return

2020-07-29 Thread Leonard Brünings
Hi,

just to throw it out there. As far as I understand this, we want to be
able to return based on the value of computed by a function without
having to assign the value to a variable first.

Another potentially more powerful alternative would be if we could
return the method from inside a closure.

def doSomething(int a) {
   callB().tap { if (a > 6 && it > 10) return@doSomething it }
   callC().tap { if ( a > 5 && it > 20) return@doSomething it }
   callD().tap { if ( a > 4 && it > 30) return@doSomething it }
}

While it may not be as concise as the original proposal, it fits better
in the existing syntax IMO.

The exact syntax of return@doSomething is up for debate, i'd imagine it
similar to break labels, with the method name being an implicit label.
Alternatively, we could use a special keyword for it.

On the discussion about "_", "$", or "it" I would strongly prefer "it"
as it would be consitent with other cases.


On a side note MG mentioned:

> (if we had "??=" as "assign iff RHS != null", "??:" for "?: with
non-nullness", and could throw where an expression was expected)

JavaScript just got a new set of conditional assignment operators
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators

Name   Shorthand operator     Meaning

Logical AND assignment       x &&= y                          x && (x = y)
Logical OR assignment          x ||= y        x ||
(x = y)
Logical nullish assignment    x ??= y                           x ?? (x = y)

Regardless of the outcome of this proposal, it might be worthwhile to
add them to groovy.

Cheers

Leo


Am 29.07.2020 um 22:28 schrieb MG:
> Hi Daniel,
>
> good idea also :-)
>
> If the arguments are in this order however, it looks like a regular if
> with its execution block to me...
> Having the method call as the second argument would express more
> intuitively what is happening - so maybe one should flip the order of
> the arguments, and use:
>
> returnIf(a > 6 && it > 10) { goo() }
>
> Cheers,
> mg
>
>
> PS: If it = callB() were to be executed lazily, and no "it" argument
> existed inside the condition, it would not be evaluated at all if
> condition evaluates to false, making
>
> returnIf() { goo() }
>
> equivalent to
>
> if() { return goo() }
>
>
>
> On 29/07/2020 05:18, Daniel Sun wrote:
>> Hi Eric,
>>
>>     I like your idea too ;-)
>>
>>     We could use closure to express the condition at the tailing of
>> method call:
>> ```
>> def doSomething(int a) {
>>    returnIf(callB()) { a > 6 && it > 10 }
>>    returnIf(callC()) { a > 5 && it > 20 }
>>    returnIf(callD()) { a > 4 && it > 30 }
>> }
>> ```
>>
>> Cheers,
>> Daniel Sun
>> On 2020/07/28 14:08:45, "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 
>>> Sent: Sunday, July 26, 2020 6:23 PM
>>> To: dev@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=02%7C01%7Ceric.milles%40thomsonreuters.com%7C411c66fda05844d7429908d831bacc9d%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637314025668554080=vNa3dz0H%2BJAegS9Zb8HW2by0ueceqCKI6qDVFpBpbc4%3D=0
>>> )
>>>> But isn't it better with pattern matching? And what is "_" here?
>>> The underscore represents the return value
>>>
>>>> Anyways:
>>>> ```
>>>> return match (_) {
>>>>  case 

Re: [PROPOSAL]Support conditional return

2020-07-29 Thread Daniel Sun
Hi mg,

 I like your idea, but it's hard for IDE to infer the type of `it` during 
we coding.

```
returnIf(a > 6 && it > 10) { goo() }
```

Cheers,
Daniel Sun
On 2020/07/29 20:28:13, MG  wrote: 
> Hi Daniel,
> 
> good idea also :-)
> 
> If the arguments are in this order however, it looks like a regular if 
> with its execution block to me...
> Having the method call as the second argument would express more 
> intuitively what is happening - so maybe one should flip the order of 
> the arguments, and use:
> 
> returnIf(a > 6 && it > 10) { goo() }
> 
> Cheers,
> mg
> 
> 
> PS: If it = callB() were to be executed lazily, and no "it" argument 
> existed inside the condition, it would not be evaluated at all if 
> condition evaluates to false, making
> 
> returnIf() { goo() }
> 
> equivalent to
> 
> if() { return goo() }
> 
> 
> 
> On 29/07/2020 05:18, Daniel Sun wrote:
> > Hi Eric,
> >
> > I like your idea too ;-)
> >
> > We could use closure to express the condition at the tailing of method 
> > call:
> > ```
> > def doSomething(int a) {
> >returnIf(callB()) { a > 6 && it > 10 }
> >returnIf(callC()) { a > 5 && it > 20 }
> >returnIf(callD()) { a > 4 && it > 30 }
> > }
> > ```
> >
> > Cheers,
> > Daniel Sun
> > On 2020/07/28 14:08:45, "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 
> >> Sent: Sunday, July 26, 2020 6:23 PM
> >> To: dev@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=02%7C01%7Ceric.milles%40thomsonreuters.com%7C411c66fda05844d7429908d831bacc9d%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637314025668554080=vNa3dz0H%2BJAegS9Zb8HW2by0ueceqCKI6qDVFpBpbc4%3D=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))
> >> }
> >>

Re: [PROPOSAL]Support conditional return

2020-07-29 Thread MG

Hi Daniel,

good idea also :-)

If the arguments are in this order however, it looks like a regular if 
with its execution block to me...
Having the method call as the second argument would express more 
intuitively what is happening - so maybe one should flip the order of 
the arguments, and use:


returnIf(a > 6 && it > 10) { goo() }

Cheers,
mg


PS: If it = callB() were to be executed lazily, and no "it" argument 
existed inside the condition, it would not be evaluated at all if 
condition evaluates to false, making


returnIf() { goo() }

equivalent to

if() { return goo() }



On 29/07/2020 05:18, Daniel Sun wrote:

Hi Eric,

I like your idea too ;-)

We could use closure to express the condition at the tailing of method call:
```
def doSomething(int a) {
   returnIf(callB()) { a > 6 && it > 10 }
   returnIf(callC()) { a > 5 && it > 20 }
   returnIf(callD()) { a > 4 && it > 30 }
}
```

Cheers,
Daniel Sun
On 2020/07/28 14:08:45, "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 
Sent: Sunday, July 26, 2020 6:23 PM
To: dev@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=02%7C01%7Ceric.milles%40thomsonreuters.com%7C411c66fda05844d7429908d831bacc9d%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637314025668554080=vNa3dz0H%2BJAegS9Zb8HW2by0ueceqCKI6qDVFpBpbc4%3D=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  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 doChooseMetho

Re: RE: [PROPOSAL]Support conditional return

2020-07-28 Thread Daniel Sun
Hi Eric,

   I like your idea too ;-)

   We could use closure to express the condition at the tailing of method call:
```
def doSomething(int a) {
  returnIf(callB()) { a > 6 && it > 10 }
  returnIf(callC()) { a > 5 && it > 20 }
  returnIf(callD()) { a > 4 && it > 30 }
}
```

Cheers,
Daniel Sun
On 2020/07/28 14:08:45, "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  
> Sent: Sunday, July 26, 2020 6:23 PM
> To: dev@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=02%7C01%7Ceric.milles%40thomsonreuters.com%7C411c66fda05844d7429908d831bacc9d%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637314025668554080=vNa3dz0H%2BJAegS9Zb8HW2by0ueceqCKI6qDVFpBpbc4%3D=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  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 doChoose

Re: [PROPOSAL]Support conditional return

2020-07-28 Thread MG

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 
Sent: Sunday, July 26, 2020 6:23 PM
To: dev@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%3D20data=02%7C01%7Ceric.milles%40thomsonreuters.com%7C411c66fda05844d7429908d831bacc9d%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637314025668554080sdata=vNa3dz0H%2BJAegS9Zb8HW2by0ueceqCKI6qDVFpBpbc4%3Dreserved=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  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  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 certai

Re: [PROPOSAL]Support conditional return

2020-07-28 Thread MG
(The boolean case is a an aggregate, the second one only reassigns if no 
value is assigned, so I would use both.
In contrast the example of yours I referred to wrote the value of foo 
every line without aggregating - this is what I found non-optimal... :-)  )


On 28/07/2020 12:30, Jochen Theodorou wrote:

On 27.07.20 18:13, MG wrote:

I am actually using this style quite often, because of a lack of good
alternatives. In the groovy code base you will find several places
looking like this:

foo = foo || m1()
foo = foo || m2()
foo = foo || m3()
foo = foo || m4()

or

foo = m1()
if (foo == null) foo = m2()
if (foo == null) foo = m3()
if (foo == null) foo = m4()

depending on if foo is a boolean or not





Re: [PROPOSAL]Support conditional return

2020-07-28 Thread MG
Like - would still be nice if we had a more Groovy syntax for 
Stream.of(...)/.stream() ... G-)


On 28/07/2020 12:30, Jochen Theodorou wrote:

well, with the streams API:


return Stream.of(null,Character.TYPE,Integer.TYPE).
  map {doChooseMethod(methodName, adjustArguments(arguments, it)}.
  findFirst {it}.
  orElseThrow {new GroovyRuntimeException("$methodName not found")}


The key here being that map is not executed eager.






RE: [PROPOSAL]Support conditional return

2020-07-28 Thread Milles, Eric (TR Technology)
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  
Sent: Sunday, July 26, 2020 6:23 PM
To: dev@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%3D20data=02%7C01%7Ceric.milles%40thomsonreuters.com%7C411c66fda05844d7429908d831bacc9d%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637314025668554080sdata=vNa3dz0H%2BJAegS9Zb8HW2by0ueceqCKI6qDVFpBpbc4%3Dreserved=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  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  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
> &g

Re: [PROPOSAL]Support conditional return

2020-07-28 Thread Jochen Theodorou

On 27.07.20 18:13, MG wrote:
[...]

Continously reassigning to methodChosen  to itself once it has been set
(or in your code: Once it has acquired a value that is Groovy-true)
seems confusing & inelegant to me.


I am actually using this style quite often, because of a lack of good
alternatives. In the groovy code base you will find several places
looking like this:

foo = foo || m1()
foo = foo || m2()
foo = foo || m3()
foo = foo || m4()

or

foo = m1()
if (foo == null) foo = m2()
if (foo == null) foo = m3()
if (foo == null) foo = m4()

depending on if foo is a boolean or not

[...]

or if adjustArguments is an identity operation if the type argument is
null (to me it is more elegant if the doChooseMethod call appears only
once):

def chooseMethod(String methodName,Object[] arguments) {
  def methodChosen = null
  [null, Character.TYPE,Integer.TYPE ].find{ methodChosen = 
doChooseMethod(methodName, adjustArguments(arguments, it))}
  if(methodChosen) {return methodChosen } else {throw new 
GroovyRuntimeException("$methodNamenot found") }
}


well, with the streams API:


return Stream.of(null,Character.TYPE,Integer.TYPE).
  map {doChooseMethod(methodName, adjustArguments(arguments, it)}.
  findFirst {it}.
  orElseThrow {new GroovyRuntimeException("$methodName not found")}


The key here being that map is not executed eager.


(Disclaimer: Dry programmed code again, so can contain stupid mistake(s))


dito

bye Jochen


Re: [PROPOSAL]Support conditional return

2020-07-27 Thread MG
I also got it wrong, because I thought what you wanted to do was 
overwrite methodChosen - but that is of course not what would happen in 
Daniel's code ;-)


Continously reassigning to methodChosen  to itself once it has been set 
(or in your code: Once it has acquired a value that is Groovy-true) 
seems confusing & inelegant to me. In this case I would prefer Daniel's 
code - or just plain old:


def chooseMethod(String methodName,Object[] arguments) {
 def methodChosen = doChooseMethod(methodName, arguments)
 [Character.TYPE,Integer.TYPE ].find{ methodChosen = doChooseMethod(methodName, 
adjustArguments(arguments, it))
  methodChosen !=null } if(methodChosen !=null){ return methodChosen }else {throw new 
GroovyRuntimeException("$methodNamenot found") }
}

or if we can use Groovy-truth as in your example instead of non-nullness:

def chooseMethod(String methodName,Object[] arguments) {
 def methodChosen = doChooseMethod(methodName, arguments)
 [Character.TYPE,Integer.TYPE ].find{ methodChosen = doChooseMethod(methodName, 
adjustArguments(arguments, it))} if(methodChosen) {return methodChosen }else {throw new 
GroovyRuntimeException("$methodNamenot found") }
}

or if adjustArguments is an identity operation if the type argument is 
null (to me it is more elegant if the doChooseMethod call appears only 
once):


def chooseMethod(String methodName,Object[] arguments) {
 def methodChosen = null
 [null, Character.TYPE,Integer.TYPE ].find{ methodChosen = doChooseMethod(methodName, 
adjustArguments(arguments, it))} if(methodChosen) {return methodChosen }else {throw new 
GroovyRuntimeException("$methodNamenot found") }
}

(Disclaimer: Dry programmed code again, so can contain stupid mistake(s))

Cheers,
mg


On 27/07/2020 12:26, Jochen Theodorou wrote:

On 27.07.20 12:19, MG wrote:

Hi Jochen,

I assume there is a typo ("?:" -> "?=") in your example, but apart from
that, Groovy-truth prohibits your solution for any method returning a
type which has special Groovy-truth meaning, so what we would need for
general applicability and terseness would be:

def chooseMethod(String methodName, Object[] arguments) {
 def methodChosen = doChooseMethod(methodName, arguments)
 methodChosen ??= doChooseMethod(methodName,
adjustArguments(arguments.clone(), Character.TYPE))
 methodChosen ??= doChooseMethod(methodName,
adjustArguments(arguments.clone(), Integer.TYPE))
 return methodChosen  ??:  throw new
GroovyRuntimeException("$methodName not found")
}


oh dear, looks like it was to early in the morning;

I did mean this:


def chooseMethod(String methodName, Object[] arguments) {
    def methodChosen = doChooseMethod(methodName, arguments)
    methodChosen = methodChosen ?: doChooseMethod(methodName, 
adjustArguments(arguments.clone(), Character.TYPE))
    methodChosen = methodChosen ?: doChooseMethod(methodName, 
adjustArguments(arguments.clone(), Integer.TYPE))

    if (null != methodChosen) return methodChosen

    throw new GroovyRuntimeException("$methodName not found")
}


bye Jochen





Re: [PROPOSAL]Support conditional return

2020-07-27 Thread Jochen Theodorou

On 25.07.20 20:55, Daniel Sun 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
}
```


I am partial to this. I can see it's use, but I find the multiple
returns a bit irritating. When I read code, then returns are important
points and I am trained to spot them as especially important and what
structure they are in. Of course I can see that even better here
(kinda), but I am not used to it. On the other hand it is so much alike
to what I am used to... I think I could easily oversee the conditional
sign. It happened to me when reading the examples actually


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
}
```


Initially I disliked this, but once I am getting more used to I find it
actually quite interesting. It makes the return a special kind of
function. Of course to be complete you would actually have to have

return {r -> r!=null} callSomeMethod()

Though there is a problem if I compare this with what we have.. because
this would mean:

return({r -> r!=null}).callSomeMethod()

command expressions, and that does not work out. Which then again brings
me back to

return(r -> r != null) callSomeMethod()

which should read as

return(r -> r != null).callSomeMethod()

and then it does not work out either. So what first looked like making
the language more using its own constructs is actually something
completely new, a special syntax just for return, that kinda overlaps
with command expressions and only doesn't do that because of the return
keyword... Nope, that part is a -1 to me right now

bye Jochen


Re: [PROPOSAL]Support conditional return

2020-07-27 Thread Mikko Värri



> On 27. Jul 2020, at 5.16, Keegan Witt  wrote:
> 
> but Kotlin is the only place I've seen a trailing if like that, so maybe 
> that's biasing my opinion


Not familiar with Kotlin, but Perl has " ".  For example:

```
doSomething() if true
```

But that is quite different from what is proposed here.  In Perl, the condition 
is evaluated first, and if it is false, the statement is not eval'd at all.  
So, it's just short for:

```
if (true)
  doSomething()
```

-mikko



Re: [PROPOSAL]Support conditional return

2020-07-27 Thread Jochen Theodorou

On 27.07.20 12:19, MG wrote:

Hi Jochen,

I assume there is a typo ("?:" -> "?=") in your example, but apart from
that, Groovy-truth prohibits your solution for any method returning a
type which has special Groovy-truth meaning, so what we would need for
general applicability and terseness would be:

def chooseMethod(String methodName, Object[] arguments) {
     def methodChosen = doChooseMethod(methodName, arguments)
     methodChosen ??= doChooseMethod(methodName,
adjustArguments(arguments.clone(), Character.TYPE))
     methodChosen ??= doChooseMethod(methodName,
adjustArguments(arguments.clone(), Integer.TYPE))
     return methodChosen  ??:  throw new
GroovyRuntimeException("$methodName not found")
}


oh dear, looks like it was to early in the morning;

I did mean this:


def chooseMethod(String methodName, Object[] arguments) {
def methodChosen = doChooseMethod(methodName, arguments)
methodChosen = methodChosen ?: doChooseMethod(methodName, 
adjustArguments(arguments.clone(), Character.TYPE))
methodChosen = methodChosen ?: doChooseMethod(methodName, 
adjustArguments(arguments.clone(), Integer.TYPE))
if (null != methodChosen) return methodChosen

throw new GroovyRuntimeException("$methodName not found")
}


bye Jochen



Re: [PROPOSAL]Support conditional return

2020-07-27 Thread MG

Hi Jochen,

I assume there is a typo ("?:" -> "?=") in your example, but apart from 
that, Groovy-truth prohibits your solution for any method returning a 
type which has special Groovy-truth meaning, so what we would need for 
general applicability and terseness would be:


def chooseMethod(String methodName, Object[] arguments) {
    def methodChosen = doChooseMethod(methodName, arguments)
    methodChosen ??= doChooseMethod(methodName, 
adjustArguments(arguments.clone(), Character.TYPE))
    methodChosen ??= doChooseMethod(methodName, 
adjustArguments(arguments.clone(), Integer.TYPE))
    return methodChosen  ??:  throw new 
GroovyRuntimeException("$methodName not found")

}

(if we had "??=" as "assign iff RHS != null", "??:" for "?: with 
non-nullness", and could throw where an expression was expected)


Cheers,
mg


On 27/07/2020 06:00, Jochen Theodorou wrote:

On 26.07.20 20:23, Daniel Sun 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")
}
```


now that I would now maybe write like this:


def chooseMethod(String methodName, Object[] arguments) {
    def methodChosen = doChooseMethod(methodName, arguments)
    methodChosen ?: doChooseMethod(methodName, 
adjustArguments(arguments.clone(), Character.TYPE))
    methodChosen ?: doChooseMethod(methodName, 
adjustArguments(arguments.clone(), Integer.TYPE))

    if (null != methodChosen) return methodChosen

    throw new GroovyRuntimeException("$methodName not found")
}



compared to



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")
}
```


bye Jochen




Re: [PROPOSAL]Support conditional return

2020-07-26 Thread Jochen Theodorou

On 26.07.20 20:23, Daniel Sun 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")
}
```


now that I would now maybe write like this:


def chooseMethod(String methodName, Object[] arguments) {
def methodChosen = doChooseMethod(methodName, arguments)
methodChosen ?: doChooseMethod(methodName, 
adjustArguments(arguments.clone(), Character.TYPE))
methodChosen ?: doChooseMethod(methodName, 
adjustArguments(arguments.clone(), Integer.TYPE))
if (null != methodChosen) return methodChosen

throw new GroovyRuntimeException("$methodName not found")
}



compared to



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")
}
```


bye Jochen


Re: [PROPOSAL]Support conditional return

2020-07-26 Thread Keegan Witt
> Second, WRT the syntax of Kotlin, it mixes the expressions and
statements. But Groovy extends the design of Java, which does not support
the mixing.
I wasn't saying we should support that because Kotlin does.  I'm saying
because we *won't* support both usages, it makes it feel more out of place
to me (but Kotlin is the only place I've seen a trailing if like that, so
maybe that's biasing my opinion).  It feels like new syntax for just one
specific use case.

-Keegan

On Sun, Jul 26, 2020 at 8:50 PM Mikko Värri  wrote:

> I'm leaning towards +1 for the simpler cases, but referencing earlier
> (labeled) return expression values via `label._` syntax... doesn't feel
> like Groovy anymore, IMHO.  OTOH, just because I wouldn't use it doesn't
> mean it's a bad idea.
>
> So, if I've understood the proposal, I'd limit it to:
>
>  * extend return statement to include form `return  if ()`
>  * the parentheses around  are optional
>  * the  is evaluated first
>  * the  can reference the value of  via an implicit variable
>  * include short form `return? `
>
> Earlier emails talked about supporting full closure syntax for .
> Is this still included?  If so, the implicit variable would naturally be
> the closure parameter (`it` usually).  Would it make sense to use the `it`
> name even in "plain expression" form, instead of `_` or `$`?  To me, `_`
> denotes an ignored parameter, and `$` looks like something internal added
> by some AST transform.
>
> Is the short form short for avoiding null return value, or short for
> Groovy truthiness check?  All the use cases shown are for the former, but
> it feels like the latter (b/c it is short for an if clause).
>
> -mikko
>
>


Re: [PROPOSAL]Support conditional return

2020-07-26 Thread Mikko Värri
I'm leaning towards +1 for the simpler cases, but referencing earlier (labeled) 
return expression values via `label._` syntax... doesn't feel like Groovy 
anymore, IMHO.  OTOH, just because I wouldn't use it doesn't mean it's a bad 
idea.

So, if I've understood the proposal, I'd limit it to:

 * extend return statement to include form `return  if ()`
 * the parentheses around  are optional
 * the  is evaluated first
 * the  can reference the value of  via an implicit variable
 * include short form `return? `

Earlier emails talked about supporting full closure syntax for .  Is 
this still included?  If so, the implicit variable would naturally be the 
closure parameter (`it` usually).  Would it make sense to use the `it` name 
even in "plain expression" form, instead of `_` or `$`?  To me, `_` denotes an 
ignored parameter, and `$` looks like something internal added by some AST 
transform.

Is the short form short for avoiding null return value, or short for Groovy 
truthiness check?  All the use cases shown are for the former, but it feels 
like the latter (b/c it is short for an if clause).

-mikko



Re: [PROPOSAL]Support conditional return

2020-07-26 Thread Daniel Sun
Hi Keegan,

First, maybe we could use `$` instead of `_` to represent the return value, 
e.g.
```
   return callA() if $ > 5
```

Second, WRT the syntax of Kotlin, it mixes the expressions and statements. 
But Groovy extends the design of Java, which does not support the mixing.

Third, the current proposal supports referencing other return value, but 
does not support referencing each other, which is similar to the problem of 
chicken and egg.

If the labels of statements have duplicated names, the parser will throw 
errors ;-)

Cheers,
Daniel Sun
On 2020/07/26 18:21:23, Keegan Witt  wrote: 
> For context, here's a summary of a discussion we had outside this thread.
> 
> Like MG, I mostly use multiple returns for early bailouts of the method,
> and only occasionally otherwise where it adds additional readability.  I
> don't find the standard Java-like syntax for your use case
> overly-cumbersome, i.e.
> def _
> if ((_ = doA()) != null) { return _ }
> else if ((_ = doB()) > 10) { return _ }
> else if ((_ = doC()) < 10) { return _ }
> return defaultValue
> 
> I have three concerns about this proposal.  First, _ is already a valid
> identifier, so it'd be a breaking change to change its meaning. Second, it
> feels inconsistent to introduce a single way in which an if can be trailing
> (in Kotlin I think this feels consistent because it can be used in both
> assignments and returns).  Third, this seems like syntax to support a
> rather specific use-case.  For example, what if I have more than one
> variable involved in my multiple returns.  For example, how would this be
> represented?
> def a = callA()
> def b = callB()
> if (a > b && b > 1) return a
> else if (b > a && a > 10) return b
> return 0
> 
> This last example is what his latest post is in response to.
> 
> On that syntax, it would reuse the same syntax as labels on loops.  Let's
> say the methods invoked have side-effect behavior on this.done.  I haven't
> dug into the code, but would we be able to handle (or fail compilation for)
> something like
> returnA:
> while (!this.done) {
>   if (this.isSpecialCase() break returnA
>   returnA:
>   return callA() if _ > 5
>   return callB() if _ > 10 && returnA._ > 1
> }
> return this.defaultValue
> 
> -Keegan
> 
> On Sun, Jul 26, 2020 at 1:11 PM MG  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  if 
> > for the more complex one*.
> >
> > I find
> > return(
> > 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  
> >  wrote:
> >
> > Hi all:
> >
> > Very 

Re: [PROPOSAL]Support conditional return

2020-07-26 Thread Daniel Sun
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  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  if 
> for the more complex one*.
> 
> I find
> return(
> 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  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 

Re: [PROPOSAL]Support conditional return

2020-07-26 Thread Keegan Witt
For context, here's a summary of a discussion we had outside this thread.

Like MG, I mostly use multiple returns for early bailouts of the method,
and only occasionally otherwise where it adds additional readability.  I
don't find the standard Java-like syntax for your use case
overly-cumbersome, i.e.
def _
if ((_ = doA()) != null) { return _ }
else if ((_ = doB()) > 10) { return _ }
else if ((_ = doC()) < 10) { return _ }
return defaultValue

I have three concerns about this proposal.  First, _ is already a valid
identifier, so it'd be a breaking change to change its meaning. Second, it
feels inconsistent to introduce a single way in which an if can be trailing
(in Kotlin I think this feels consistent because it can be used in both
assignments and returns).  Third, this seems like syntax to support a
rather specific use-case.  For example, what if I have more than one
variable involved in my multiple returns.  For example, how would this be
represented?
def a = callA()
def b = callB()
if (a > b && b > 1) return a
else if (b > a && a > 10) return b
return 0

This last example is what his latest post is in response to.

On that syntax, it would reuse the same syntax as labels on loops.  Let's
say the methods invoked have side-effect behavior on this.done.  I haven't
dug into the code, but would we be able to handle (or fail compilation for)
something like
returnA:
while (!this.done) {
  if (this.isSpecialCase() break returnA
  returnA:
  return callA() if _ > 5
  return callB() if _ > 10 && returnA._ > 1
}
return this.defaultValue

-Keegan

On Sun, Jul 26, 2020 at 1:11 PM MG  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  if 
> for the more complex one*.
>
> I find
> return(
> 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  
>  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.ghttps://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 

Re: [PROPOSAL]Support conditional return

2020-07-26 Thread Daniel Sun
Reference other return value with the following syntax:

```
returnA:
return callA() if _ > 5

return callB() if _ > 10 && returnA._ > 1
```

Cheers,
Daniel Sun
On 2020/07/25 19:57:16, Daniel Sun  wrote: 
> Or a more verbose version:
> 
> ```
> return callB() if (r -> r > 10)
> ```
> 
> Cheers,
> Daniel Sun
> On 2020/07/25 19:51:47, Daniel Sun  wrote: 
> > If we take intellisense of IDE into account, the proposal could be refined 
> > as follows:
> > 
> > ```
> > return callB() [r -> r > 10]
> > ```
> > 
> > Cheers,
> > Daniel Sun
> > On 2020/07/25 19:39:20, Daniel Sun  wrote: 
> > > Hi OC,
> > > 
> > > Let me make the example a bit more complicated to clarify my proposal:
> > > 
> > > ```
> > > 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 above code could be simplified as follows:
> > > ```
> > > def m() {
> > >return? callA()   // same to `return(r -> null != r) 
> > > callA()`
> > >return(r -> r > 10) callB()
> > >return(r -> null != r && r < 10) callC()
> > > 
> > >LOGGER.debug('the default value will be returned')
> > > 
> > >return defaultValue
> > > }
> > > ```
> > > 
> > > Cheers,
> > > Daniel Sun
> > > On 2020/07/25 19:21:01, OCsite  wrote: 
> > > > Daniel,
> > > > 
> > > > -1. In my personal experience this happens very rarely, not worth a 
> > > > special support in the language by far. Almost all similar cases for me 
> > > > are covered by simple
> > > > 
> > > > def foo() {
> > > >   ... ...
> > > >   bar()?:defaultValue
> > > > }
> > > > 
> > > > and the cases where this is not adequate, either due a non-null false 
> > > > return value which should be returned instead of the default, or due to 
> > > > a non-trivial code needed at //! below, in my code almost never happen.
> > > > 
> > > > Contrariwise, if you are about to improve the language for simplicity 
> > > > and easiness of returns, you definitely should consider allowing 
> > > > returning void from a void method — this should be a completely valid 
> > > > code (as is e.g., in C):
> > > > 
> > > > void foo() { ... }
> > > > void bar() {
> > > >   return foo()
> > > > }
> > > > 
> > > > As always, of course, YMMV.
> > > > 
> > > > All the best,
> > > > OC
> > > > 
> > > > > On 25 Jul 2020, at 20:55, Daniel Sun  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
> > > > 
> > > > 
> > > 
> > 
> 


Re: [PROPOSAL]Support conditional return

2020-07-26 Thread MG

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  if 
for the more complex one*.

I find
return(
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  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.


Re: [PROPOSAL]Support conditional return

2020-07-26 Thread Daniel Sun
Hi Mario,

> 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.

Actually even if there are only two exit points, ternary or elvis operators are 
hard to meet all our requirements:

```
def m() {
def a = callA()
if (a !=null && a > 10) return a

// some more statements here, e.g. logging
LOGGER.debug("returning the result of callB")

return callB()
}
```

We could simplify the above as follows:
```
def m() {
return callA() if _ !=null && _ > 10

// some more statements here, e.g. logging
LOGGER.debug("returning the result of callB")

return callB()
}
```

But I have no idea how to simplify the code with ternary or elvis operators...

Cheers,
Daniel Sun
On 2020/07/26 11:29:39, Mario Garcia  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  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
> >>
> >
> 


Re: [PROPOSAL]Support conditional return

2020-07-26 Thread Daniel Sun
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  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  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
> >> 

Re: [PROPOSAL]Support conditional return

2020-07-26 Thread Mario Garcia
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  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
>>
>


Re: [PROPOSAL]Support conditional return

2020-07-25 Thread Paolo Di Tommaso
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  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
>


Re: [PROPOSAL]Support conditional return

2020-07-25 Thread Daniel Sun
Or a more verbose version:

```
return callB() if (r -> r > 10)
```

Cheers,
Daniel Sun
On 2020/07/25 19:51:47, Daniel Sun  wrote: 
> If we take intellisense of IDE into account, the proposal could be refined as 
> follows:
> 
> ```
> return callB() [r -> r > 10]
> ```
> 
> Cheers,
> Daniel Sun
> On 2020/07/25 19:39:20, Daniel Sun  wrote: 
> > Hi OC,
> > 
> > Let me make the example a bit more complicated to clarify my proposal:
> > 
> > ```
> > 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 above code could be simplified as follows:
> > ```
> > def m() {
> >return? callA()   // same to `return(r -> null != r) 
> > callA()`
> >return(r -> r > 10) callB()
> >return(r -> null != r && r < 10) callC()
> > 
> >LOGGER.debug('the default value will be returned')
> > 
> >return defaultValue
> > }
> > ```
> > 
> > Cheers,
> > Daniel Sun
> > On 2020/07/25 19:21:01, OCsite  wrote: 
> > > Daniel,
> > > 
> > > -1. In my personal experience this happens very rarely, not worth a 
> > > special support in the language by far. Almost all similar cases for me 
> > > are covered by simple
> > > 
> > > def foo() {
> > >   ... ...
> > >   bar()?:defaultValue
> > > }
> > > 
> > > and the cases where this is not adequate, either due a non-null false 
> > > return value which should be returned instead of the default, or due to a 
> > > non-trivial code needed at //! below, in my code almost never happen.
> > > 
> > > Contrariwise, if you are about to improve the language for simplicity and 
> > > easiness of returns, you definitely should consider allowing returning 
> > > void from a void method — this should be a completely valid code (as is 
> > > e.g., in C):
> > > 
> > > void foo() { ... }
> > > void bar() {
> > >   return foo()
> > > }
> > > 
> > > As always, of course, YMMV.
> > > 
> > > All the best,
> > > OC
> > > 
> > > > On 25 Jul 2020, at 20:55, Daniel Sun  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
> > > 
> > > 
> > 
> 


Re: [PROPOSAL]Support conditional return

2020-07-25 Thread Daniel Sun
If we take intellisense of IDE into account, the proposal could be refined as 
follows:

```
return callB() [r -> r > 10]
```

Cheers,
Daniel Sun
On 2020/07/25 19:39:20, Daniel Sun  wrote: 
> Hi OC,
> 
> Let me make the example a bit more complicated to clarify my proposal:
> 
> ```
> 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 above code could be simplified as follows:
> ```
> def m() {
>return? callA()   // same to `return(r -> null != r) 
> callA()`
>return(r -> r > 10) callB()
>return(r -> null != r && r < 10) callC()
> 
>LOGGER.debug('the default value will be returned')
> 
>return defaultValue
> }
> ```
> 
> Cheers,
> Daniel Sun
> On 2020/07/25 19:21:01, OCsite  wrote: 
> > Daniel,
> > 
> > -1. In my personal experience this happens very rarely, not worth a special 
> > support in the language by far. Almost all similar cases for me are covered 
> > by simple
> > 
> > def foo() {
> >   ... ...
> >   bar()?:defaultValue
> > }
> > 
> > and the cases where this is not adequate, either due a non-null false 
> > return value which should be returned instead of the default, or due to a 
> > non-trivial code needed at //! below, in my code almost never happen.
> > 
> > Contrariwise, if you are about to improve the language for simplicity and 
> > easiness of returns, you definitely should consider allowing returning void 
> > from a void method — this should be a completely valid code (as is e.g., in 
> > C):
> > 
> > void foo() { ... }
> > void bar() {
> >   return foo()
> > }
> > 
> > As always, of course, YMMV.
> > 
> > All the best,
> > OC
> > 
> > > On 25 Jul 2020, at 20:55, Daniel Sun  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
> > 
> > 
> 


Re: [PROPOSAL]Support conditional return

2020-07-25 Thread Daniel Sun
Hi OC,

Let me make the example a bit more complicated to clarify my proposal:

```
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 above code could be simplified as follows:
```
def m() {
   return? callA()   // same to `return(r -> null != r) callA()`
   return(r -> r > 10) callB()
   return(r -> null != r && r < 10) callC()

   LOGGER.debug('the default value will be returned')

   return defaultValue
}
```

Cheers,
Daniel Sun
On 2020/07/25 19:21:01, OCsite  wrote: 
> Daniel,
> 
> -1. In my personal experience this happens very rarely, not worth a special 
> support in the language by far. Almost all similar cases for me are covered 
> by simple
> 
> def foo() {
>   ... ...
>   bar()?:defaultValue
> }
> 
> and the cases where this is not adequate, either due a non-null false return 
> value which should be returned instead of the default, or due to a 
> non-trivial code needed at //! below, in my code almost never happen.
> 
> Contrariwise, if you are about to improve the language for simplicity and 
> easiness of returns, you definitely should consider allowing returning void 
> from a void method — this should be a completely valid code (as is e.g., in 
> C):
> 
> void foo() { ... }
> void bar() {
>   return foo()
> }
> 
> As always, of course, YMMV.
> 
> All the best,
> OC
> 
> > On 25 Jul 2020, at 20:55, Daniel Sun  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
> 
> 


Re: [PROPOSAL]Support conditional return

2020-07-25 Thread OCsite
Daniel,

-1. In my personal experience this happens very rarely, not worth a special 
support in the language by far. Almost all similar cases for me are covered by 
simple

def foo() {
  ... ...
  bar()?:defaultValue
}

and the cases where this is not adequate, either due a non-null false return 
value which should be returned instead of the default, or due to a non-trivial 
code needed at //! below, in my code almost never happen.

Contrariwise, if you are about to improve the language for simplicity and 
easiness of returns, you definitely should consider allowing returning void 
from a void method — this should be a completely valid code (as is e.g., in C):

void foo() { ... }
void bar() {
  return foo()
}

As always, of course, YMMV.

All the best,
OC

> On 25 Jul 2020, at 20:55, Daniel Sun  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