groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From h...@abula.org
Subject Re: suggestion: ImplicitSafeNavigation annotation
Date Tue, 14 Aug 2018 13:49:21 GMT
Den 2018-08-14 15:23, skrev ocs@ocs:
> H2,
> 
>> However, “a+b” should work as one would expect
> 
> Absolutely. Me, I very definitely expect that if a happens to be null,
> the result is null too. (With b null it depends on the details of
> a.plus implementation.)

I kind of expected that... :-) I am curious about what others think, 
though.

>> If you want a shorthand notation for “a?.plus(b)” I'd say
>> “a?+b” was more consistent
> 
> quite, it might be worth adding to the language too; but it is
> irrelevant to the current case, where the problem with this approach
> is that
> 
>> there are cases when one simply wants a bigger block of code to
>> contain only null-propagating expressions and never NPE; in such
>> case, using the question mark syntax is both inconvenient and
>> error-prone (for it is very easy to forget one of the lot of
>> question marks needed in such a code, and then get an uncaught
>> unwanted NPE).
> 
> As for
> 
>> it would be impossible to know by looking at just the code how it is
>> going to behave
> 
> it would be actually easier than it is now: checking whether an
> annotation is used somewhere is _worlds_ easier than checking whether
> perhaps the Null.metaclass happens not to be overridden with one
> returning null from its invokeMethod — which anyone can do anytime.
> 
>> Wouldn't this create potential problems when the code finds its way
>> into different project by means of dependencies?
> 
> I think not; quite the contrary. When calling a 3rd party code, you
> can't ever know whether the NPE inside of there is caught or not
> anyway, can you?

If it's caught, I expect some some default value to be returned or 
exceptional handling to take place which yields the returned value.

If it isn't, I'll get the exception thrown in my face and will be forced 
to deal with it.

I fear that "safe arithmetic evaluation" may generate more null values 
than it should. If there is a difference between the semantics of "no 
value" and "failing to evaluate", I wouldn't want to obscure this by 
representing them the same way.


> And again as above, whilst an annotation would not be
> self-evident either, it would be at the very least considerably more
> intention-revealing and self-documenting than the current
> “equivalent” of a 3rd party method
> 
> ===
> def foo() {
>   try {
>     ... body which might NPE ...
>   } catch (java.lang.NullPointerException npe) {
>     null
>   }
> }
> ===
> 
> happens to be now.
> 
> Thanks and all the best,
> OC
> 
>> On 14 Aug 2018, at 2:50 PM, h2gr@abula.org wrote:
>> 
>> Den 2018-08-14 14:25, skrev ocs@ocs:
>> H2,
>> On 14 Aug 2018, at 1:38 PM, h2gr@abula.org wrote:
>> IMHO, there is an ever so subtle difference between navigation -
>> using the . operator explictly or implicitly (as with indexing) -
>> and arithmetic.
>> do please correct me if I am wrong, but I understand in Groovy,
>> arithmetic should be just a convenience thin syntactic sugar over
>> messages; e.g., “a+b” should be full equivalent to
>> “a.plus(b)”, but
>> for the syntactic inconvenience:
>> 
> http://docs.groovy-lang.org/latest/html/documentation/#Operator-Overloading
>> To me it seems rather unlucky and inconsistent that although I can
>> write “a?.plus(b)”, I can't do precisely the same with its more
>> convenient “a+b” equivalent. With other operators it is even
>> more
>> important, e.g., “a<<b”, which, in my experience, is used much
>> more
>> often as a shorthand for something like “a.append(b)” with
>> generic
>> objects a and b than as a numeric shift.
> 
> As a matter of personal preference, this is fine with me. If you write
> “a?.plus(b)” you are explicitly going out on a limb, and it is
> explicitly visible what you're doing.
> 
> However, “a+b” should work as one would expect. What might one
> expect? I guess that something to vote over, but I propose that at the
> very least, one should not expect unexpected errors or errors that are
> hard to catch or test. It's better to catch null-related errors where
> they occur than somewhere else because an entire expression gets
> evaluated to null instead of throwing an exception.
> 
> If you want a shorthand notation for “a?.plus(b)” I'd say
> “a?+b” was more consistent (but I am by no means suggesting it).
> 
>>> I am personally perfectly happy for my arithmetic expressions to
>>> fail with any applicable exception if I throw unacceptable values
>>> at them.
>> As for the (in)convenience of NPE vs null-propagation (or, in other
>> words, (un)acceptability of nulls inside expressions), I guess it
>> would rather be in the eye of the beholder.
>> Do please note though I am not suggesting to remove the possibility
>> to
>> rely on NPE which you cherish, nor I am suggesting even changing the
>> default behaviour in the slightest; what I would like to see in
>> Groovy
>> would be a way to intentionally switch to the non-NPE
>> null-propagating
>> behaviour where needed by very explicit using of an appropriate
>> annotation. You, of course, would never be forced to use the thing
>> :)
> 
> Of course not, but it would be impossible to know by looking at just
> the code how it is going to behave.
> 
> Wouldn't this create potential problems when the code finds its way
> into different project by means of dependencies?
> 
>> Thanks and all the best,
>> OC
> 
> Ditto! :-)
> 
> H2
> 
>> Den 2018-08-14 13:28, skrev ocs@ocs:
>> Gentlemen,
>> some NPE-related problems of today brought me to re-interate one of
>> my
>> older suggestions.
>> We have the so-called “safe navigation”[*], which in some cases
>> allows
>> a null to be propagated out of an expression instead of throwing a
>> NPE. At the moment, it can be triggered for a particular
>> sub-expression (like property/method-call and, as of 3, newly also
>> indexing) using a question mark (e.g., “foo?.bar()” or
>> “foo?[bar]”).
>> Do please correct me if I am wrong, but far as I know, there still
>> are
>> expressions which do not allow the “safe mode”, e.g., arithmetic
>> (“a+b” etc). Furthermore, there are cases when one simply wants
>> a
>> bigger block of code to contain only null-propagating expressions
>> and
>> never NPE; in such case, using the question mark syntax is both
>> inconvenient and error-prone (for it is very easy to forget one of
>> the
>> lot of question marks needed in such a code, and then get an
>> uncaught
>> unwanted NPE).
>> For these reasons, I would suggest adding a new annotation, whose
>> name
>> might be e.g., “ImplicitSafeNavigation”; it would simply force a
>> null-propagation to be implicitly and automatically used for *all*
>> expressions in the annotated scope, i.e., NPE would never be thrown
>> for them; for example:
>> ===
>> @ImplicitSafeNavigation class Foo {
>> static foo(a,b,c,d,e) {
>> a.bar+b*c[d]<<e.bax() // just e.g.; would work with *any*
>> expression which NPEs today
>> }
>> }
>> assert null == Foo.foo(null,null,null,null,null)
>> ===
>> I wonder whether this enhancement would be possible to implement in
>> some forthcoming Groovy release? Myself, I believe it would help
>> tremendously.
>> If feasible, then it is for a further discussion whether in the
>> scope
>> of this annotation
>> (a) a safe-navigation syntax (“foo?.bar”) should be ignored as
>> superfluous;
>> (b) or, whether in this scope it should reverse the behaviour to
>> trigger an NPE anyway;
>> (c) or, whether it should be ignored as (a), and aside of that it
>> would be worth the effort (and technically possible) to add another
>> syntax to force NPE over a particular sub-expression (e.g.,
>> “foo!.bar”).
>> Thanks and all the best,
>> OC
>> [*] The name might not be quite apt, for propagating a null is not
>> inherently safer than NPEing; those are simply two different
>> approaches, both of which serve best in different circumstances. A
>> better name would be something like “null-propagating” or
>> “non-NPE”
>> mode, I guess. Myself, I don't think we should change the name
>> though,
>> for all are used to it.

Mime
View raw message