Safe index for Groovy 3

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Safe index for Groovy 3

Daniel Sun
Hi all,

      The new parser supports safe index now, which is proposed by Paul King :)

      Here are some example code:

assert null == null?[1];
assert null == null?[1]?[1, 2];
assert null == null?[1]?[1, 2]?[1, 2, 3];

def a = null;
assert null == a?[1, 2];

def f() {return null}
assert null == f()?[1];

       More information can be found at the safeIndex branch of groovy-parser project(https://github.com/danielsun1106/groovy-parser/tree/safeIndex)

       Any thoughts?

       BTW, the antlr4 branch of apache/groovy is very old, I am going to try to update it with the master.

Cheers,
Daniel.Sun

Reply | Threaded
Open this post in threaded view
|

Re: Safe index for Groovy 3

Daniel Sun
groovy-all-2.5.0-SNAPSHOT jar file used by groovy-parser is a bit outdated, the following usual code can not be executed too(but it can be executed by 2.4.7...), so the static complication test cases will be added later :)

@CompileStatic
int cs() {
    List a = [1, 2, 3]
    return a[0];
}
cs();


Cheers,
Daniel.Sun
Reply | Threaded
Open this post in threaded view
|

Re: Safe index for Groovy 3

Guillaume Laforge
Administrator
In reply to this post by Daniel Sun
A few times I've wanted to have safe index.
Sounds like a good idea.

On Tue, Nov 8, 2016 at 5:08 PM, Daniel Sun <[hidden email]> wrote:
Hi all,

      The new parser supports safe index now, which is proposed by Paul King
:)

      Here are some example code:

assert null == null?[1];
assert null == null?[1]?[1, 2];
assert null == null?[1]?[1, 2]?[1, 2, 3];

def a = null;
assert null == a?[1, 2];

def f() {return null}
assert null == f()?[1];

       More information can be found at the safeIndex branch of
groovy-parser
project(https://github.com/danielsun1106/groovy-parser/tree/safeIndex)

       Any thoughts?

       BTW, the antlr4 branch of apache/groovy is very old, I am going to
try to update it with the master.

Cheers,
Daniel.Sun





--
View this message in context: http://groovy.329449.n5.nabble.com/Safe-index-for-Groovy-3-tp5736558.html
Sent from the Groovy Dev mailing list archive at Nabble.com.



--
Guillaume Laforge
Apache Groovy committer & PMC Vice-President
Developer Advocate @ Google Cloud Platform

Reply | Threaded
Open this post in threaded view
|

Re: Safe index for Groovy 3

Daniel Sun
Yeah, I like the idea too :)

Cheers,
Daniel.Sun
Reply | Threaded
Open this post in threaded view
|

Re: Safe index for Groovy 3

ocs@ocs
In reply to this post by Daniel Sun
Hi there,

>       Any thoughts?

Does it support properly "foo[null]", too?

That aside, I would just again like to advocate for an, let's say, „full-safe“ mode, where one could set some switch (probably would need to be a compile-time one I guess) to get implicitly the „safe mode“ for _all_ expressions (methods, indexes, operators -- have I forgot anything?) without a need to write all those pesky ?'s explicitly.

Thanks and all the best,
OC

> On 8. 11. 2016, at 5:08 PM, Daniel Sun <[hidden email]> wrote:
>
> Hi all,
>
>      The new parser supports safe index now, which is proposed by Paul King
> :)
>
>      Here are some example code:
>
> assert null == null?[1];
> assert null == null?[1]?[1, 2];
> assert null == null?[1]?[1, 2]?[1, 2, 3];
>
> def a = null;
> assert null == a?[1, 2];
>
> def f() {return null}
> assert null == f()?[1];
>
>       More information can be found at the safeIndex branch of
> groovy-parser
> project(https://github.com/danielsun1106/groovy-parser/tree/safeIndex)
>
>       Any thoughts?
>
>       BTW, the antlr4 branch of apache/groovy is very old, I am going to
> try to update it with the master.
>
> Cheers,
> Daniel.Sun
>
>
>
>
>
> --
> View this message in context: http://groovy.329449.n5.nabble.com/Safe-index-for-Groovy-3-tp5736558.html
> Sent from the Groovy Dev mailing list archive at Nabble.com.

Reply | Threaded
Open this post in threaded view
|

Re: Safe index for Groovy 3

Daniel Sun
Hi OC,

       IMHO, 'full safe' switch  will change the semantic of existing '.', which may reduce the maintainability and readability of program, so the explicit '?' is necessary. Thanks for your suggestions :)

Cheers,
Daniel.Sun
Reply | Threaded
Open this post in threaded view
|

Re: Safe index for Groovy 3

ocs@ocs
Daniel,

On 9. 11. 2016, at 15:49, Daniel Sun <[hidden email]> wrote:

>       IMHO, 'full safe' switch  will change the semantic of existing '.'

Absolutely.

> which may reduce the maintainability and readability of program

Quite the contrary.

As always, I might be overlooking something of importance, but it seems to be whomever whose code relies on NPE would never use that switch [*].

On the other hand, for us who *NEVER* want to see *ANY* NPE, and at the moment, are thus forced to an ugly mess of special null metaclasses and ASTTs, it would help tremendously, making the code considerably more stable and safer (e.g., since those ASTTs tend to clash with traits, and who know with what else in future).

Now, [*] I have (just again!) forgot the terrible Java-induced approach of building whole project, instead of compiling each source file separately, as it always used to be with decent languages. Dang. This means my suggested approach of a compiler switch would indeed get dangerous with sources, added to project, but maintained by another party -- which sources might depend on the NPE, and the compiler switch would cause precisely the problems you mention. Therefore, a compiler switch is actually out of question.

Hmmm.... what about a class-level annotation, which would direct the compiler (and possibly runtime) to behave appropriately? Something like

@AlwaysSafe class foo {
  def bar(a,b,c,d) { // this method never NPEs; if any argument is null, it simply returns null
    a.foo+b+c[d] // and so forth with any other operation
  }
}

That would be, in my personal opinion, completely safe, and would help a lot?

Thanks and all the best,
OC


Reply | Threaded
Open this post in threaded view
|

Re: Safe index for Groovy 3

ocs@ocs
P.S. just to stay at the precise side...

On 9. 11. 2016, at 16:33, OC <[hidden email]> wrote:

> @AlwaysSafe class foo {
>  def bar(a,b,c,d) { // this method never NPEs

unless a.foo implementation does, of course!

> ; if any argument is null, it simply returns null
>    a.foo+b+c[d] // and so forth with any other operation
>  }
> }

Reply | Threaded
Open this post in threaded view
|

Re: Safe index for Groovy 3

Cédric Champeau
In reply to this post by ocs@ocs
Not throwing an NPE doesn't mean you are safe. It means it doesn't throw errors, but you gave away on semantics. NPEs are often blamed, but they correspond to developer errors. Only the developer knows if null is relevant or not. I'm totally -1 on this.

2016-11-09 16:33 GMT+01:00 OC <[hidden email]>:
Daniel,

On 9. 11. 2016, at 15:49, Daniel Sun <[hidden email]> wrote:

>       IMHO, 'full safe' switch  will change the semantic of existing '.'

Absolutely.

> which may reduce the maintainability and readability of program

Quite the contrary.

As always, I might be overlooking something of importance, but it seems to be whomever whose code relies on NPE would never use that switch [*].

On the other hand, for us who *NEVER* want to see *ANY* NPE, and at the moment, are thus forced to an ugly mess of special null metaclasses and ASTTs, it would help tremendously, making the code considerably more stable and safer (e.g., since those ASTTs tend to clash with traits, and who know with what else in future).

Now, [*] I have (just again!) forgot the terrible Java-induced approach of building whole project, instead of compiling each source file separately, as it always used to be with decent languages. Dang. This means my suggested approach of a compiler switch would indeed get dangerous with sources, added to project, but maintained by another party -- which sources might depend on the NPE, and the compiler switch would cause precisely the problems you mention. Therefore, a compiler switch is actually out of question.

Hmmm.... what about a class-level annotation, which would direct the compiler (and possibly runtime) to behave appropriately? Something like

@AlwaysSafe class foo {
  def bar(a,b,c,d) { // this method never NPEs; if any argument is null, it simply returns null
    a.foo+b+c[d] // and so forth with any other operation
  }
}

That would be, in my personal opinion, completely safe, and would help a lot?

Thanks and all the best,
OC



Reply | Threaded
Open this post in threaded view
|

Re: Safe index for Groovy 3

ocs@ocs
Cédric,

On 9. 11. 2016, at 16:37, Cédric Champeau <[hidden email]> wrote:

> Not throwing an NPE doesn't mean you are safe.

Absolutely. Myself, I do not like the name, but it is a Groovy thing -- you (unlike me) should probably know who decided to name the ?. thing a “safe navigation”. In my personal vocabulary it is neither safe, nor a navigation; but for consistency, I just keep using the vocabulary of yours.

> It means it doesn't throw errors, but you gave away on semantics. NPEs are often blamed, but they correspond to developer errors.

Quite the contrary. The only thing they do is promoting bloatware and ugly boilerplate, namely, zillions of “if (foo!=nil) foo.bar()” etc. in Java code.

The Groovy way of “foo?.bar()“ is much better, but still far from perfect.

The perfect way is simply “foo.bar()” for the same behaviour.

> Only the developer knows if null is relevant or not.

Precisely, that's the very reason for my suggestion. In those very rare cases where it makes sense to check for null inside of an expression (instead of, as in 99.99 % of cases, at the result), he explicitly checks and takes an appropriate course, instead of getting an unwanted, surprising and potentially disastrous NPE.

> I'm totally -1 on this.

Pity, it would improve Groovy considerably.

(Along with another possibility to switch off -- preferrably through an annotation, too -- the just as terrible GroovyCastException, which leads to very ugly contraptions instead of clean, concise and stable proxying; but that's another story, and based on some older debates with Jochen I am afraid this would not be possible at all, for the exception probably is caused by JVM and can't be dodged anyhow.)

Thanks and all the best,
OC

> 2016-11-09 16:33 GMT+01:00 OC <[hidden email]>:
> Daniel,
>
> On 9. 11. 2016, at 15:49, Daniel Sun <[hidden email]> wrote:
>
> >       IMHO, 'full safe' switch  will change the semantic of existing '.'
>
> Absolutely.
>
> > which may reduce the maintainability and readability of program
>
> Quite the contrary.
>
> As always, I might be overlooking something of importance, but it seems to be whomever whose code relies on NPE would never use that switch [*].
>
> On the other hand, for us who *NEVER* want to see *ANY* NPE, and at the moment, are thus forced to an ugly mess of special null metaclasses and ASTTs, it would help tremendously, making the code considerably more stable and safer (e.g., since those ASTTs tend to clash with traits, and who know with what else in future).
>
> Now, [*] I have (just again!) forgot the terrible Java-induced approach of building whole project, instead of compiling each source file separately, as it always used to be with decent languages. Dang. This means my suggested approach of a compiler switch would indeed get dangerous with sources, added to project, but maintained by another party -- which sources might depend on the NPE, and the compiler switch would cause precisely the problems you mention. Therefore, a compiler switch is actually out of question.
>
> Hmmm.... what about a class-level annotation, which would direct the compiler (and possibly runtime) to behave appropriately? Something like
>
> @AlwaysSafe class foo {
>   def bar(a,b,c,d) { // this method never NPEs; if any argument is null, it simply returns null
>     a.foo+b+c[d] // and so forth with any other operation
>   }
> }
>
> That would be, in my personal opinion, completely safe, and would help a lot?
>
> Thanks and all the best,
> OC
>
>
>