Probable bug in null-coalescing operator

48 views
Skip to first unread message

Adam Cameron

unread,
Feb 18, 2014, 6:56:29 PM2/18/14
to ra...@googlegroups.com
G'day:
This follows on from the discussion which started by discussing augmenting structKeyExists(), but has drawn my attention to the null-coalescing operation (ie: "?:". I'm fucked if I'm gonna use the word "Elvis" in the context of that thing).

Anyway, this code does not error:

  a = {}
  result = a.b.c ?: "default"
  echo(result)

But it should. It should error with something along the lines of c not existing.

Here is the equivalent Groovy code:

def a = [:]
def result = a.b.c ?: "default"
println(result)


This - correctly - errors with:

Caught: java.lang.NullPointerException: Cannot get property 'c' on null object

This is what Railo should do also.

There is a difference between the operator dealing with null values (which it does correctly), but it's overreaching, I think, to pretend it makes any sort of sense for a.b (which is null) to have a property c. That's just wrong. a.b.c isn't null, it simply doesn't exist (which are two different things).

This is where the safe navigation operator comes in:

def a = [:]
def result = a.b?.c ?: "default"
println(result)

This is now this sort of thing should be dealt with.

-- 
Adam

Igal @ getRailo.org

unread,
Feb 18, 2014, 7:03:35 PM2/18/14
to ra...@googlegroups.com
why should it error? 

the whole idea is to allow you to use a default value without worrying about each level in the chain.
--
Did you find this reply useful? Help the Railo community and add it to the Railo Server wiki at https://github.com/getrailo/railo/wiki
---
You received this message because you are subscribed to the Google Groups "Railo" group.
To view this discussion on the web visit https://groups.google.com/d/msgid/railo/7b8dc94e-275f-477d-9c5c-096c34d586e6%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

-- 
Igal Sapir
Railo Core Developer
http://getRailo.org/

Adam Cameron

unread,
Feb 18, 2014, 7:17:07 PM2/18/14
to ra...@googlegroups.com
No. The "whole idea" of the operator is that the result of the operation is the first operand's value if it's not null, otherwise the result is the second operand's value. That's it.

a.b.c isn't null in that example; it doesn't exist. So it should error. a.b.c in the example is an invalid expression: b is null, so it cannot have a property c. 

You are mishmashing the idea of "null coalescing" with "safe navigation". They're two different operators.

-- 
Adam

Igal @ getRailo.org

unread,
Feb 18, 2014, 7:32:43 PM2/18/14
to ra...@googlegroups.com
I'm not mishmashing anything. 

do you happen to have the Railo Specification for the Elvis Operator?  and no, other operators from other languages do not qualify, however similar you think that they are to the one we're talking about.

For more options, visit https://groups.google.com/groups/opt_out.

Adam Cameron

unread,
Feb 18, 2014, 7:50:35 PM2/18/14
to ra...@googlegroups.com
Oh, go on then Igal. Do share. Share the spec which you have which states "despite a clear precedent in other languages, and defying obvious intent of the operator, and flying in the face of common sense, we're going to implement it this way instead: [followed by details of the implementation]".

Share that doc with us.

Go on.

I await with bated breath.

-- 
Adam

Igal @ getRailo.org

unread,
Feb 18, 2014, 7:55:25 PM2/18/14
to ra...@googlegroups.com
there were several communications on the subject, and they are consistent with the implementation.  you are the one who seems to have an issue with it.  not me.

For more options, visit https://groups.google.com/groups/opt_out.

Adam Cameron

unread,
Feb 18, 2014, 8:40:41 PM2/18/14
to ra...@googlegroups.com
Sorry Igal, you mentioned a spec.

And, yes, I do have an issue with the implementation, because the implementation seems slightly wrong. It very much seems to me like - with the best of intents - you guys got it slightly wrong. This is my point. But "[shrug]shit happens"... there's no need to get arsey about it, and there's no need to get defensive about it either. And if you try to patronisingly insult my intelligence by squirming about and citing fictitious specs which you then can't produce (because, like, it doesn't exist, does it? No. Let's move on)... I think we all know how well that's going to go. So let's just stay objective and honest, shall we? Thanks.

So...  that said... even if you did specifically plan to implement it the way that you have, I think you need to step back and give some thought to whether that was the right thing to do, and accordingly whether it's actually been implemented how it should have been. Because - as per the evidence I posted in my first message - it seems to be... slightly wrong. Somehow in the implementation of the ?: operator, you've done something weird with the dot operator. Because the dot operator should error when applied to an object that is null. You should get an error in this situation. And that's got nothing to do with the ?: operator, which is merely supposed to be checking whether the first operand is null. Not if it's *invalid or null*, which is what it seems to be doing. That is incorrect behaviour.

Now... if you can explain to me where I am mistaken in the assertions I've made, all good. If you're just gonna go "it's right you're wrong"... then perhaps you've already covered that ground and there's no need to restate it. I'm happpy to wait for Micha to take a look at this and to see what he has to say.

Cheers.

-- 
Adam

Gert Franz

unread,
Feb 18, 2014, 8:49:58 PM2/18/14
to ra...@googlegroups.com
Guys,

First off all, let's take the tension out of it. Afaik the original implementation was that it should follow what the Elvis operator was supposed to do, even though I find it as it is very handy, since I want that expression not to throw an error in ANY case. Whether it follows Groovy or not, I honestly don't care. As I understand the Elvis operator it will check what's before the operator and if it exists will use that value, otherwise the default. Whether it is null or does not exist is actually irrelevant to me since the concept of null is not really completely implemented CFML, right?
That's my personal opinion. 

But, as you wrote Adam, let's hear what Micha and the others have to say about it.

Gert

Von meinem iPad gesendet
--
Did you find this reply useful? Help the Railo community and add it to the Railo Server wiki at https://github.com/getrailo/railo/wiki
---
You received this message because you are subscribed to the Google Groups "Railo" group.

Jean Moniatte

unread,
Feb 19, 2014, 2:31:02 AM2/19/14
to Railo Google Group

On Wed, Feb 19, 2014 at 2:49 AM, Gert Franz <ge...@getrailo.com> wrote:
I want that expression not to throw an error in ANY case

+1. Please keep it that way.

Michael Offner

unread,
Feb 20, 2014, 4:48:28 AM2/20/14
to ra...@googlegroups.com
in my opinion, handling the condition of the elvis operator should never throw a exception.
in a language that supporting the safe operator and the elvis operator your argument is perhaps valid (not in my opinion), but with railo we decided against the safe operator. 
In Railo i see the elvis operator as shortcut of the tenary operator, take this example:
a = {}
result = !isNull(a.b.c) ?a.b.c: "default"
echo(result)

you get exactly the same result!
or should the function isNull throw a exception when b does not exists? Perhaps,then a.b.c is not existing and not null.

Please have in mind that (when full null support is disabled), null and not existing is the same in CFML (in most cases).
I gave that implementation a lot of thoughts before i have implemented that way, so it was not by accident and it is not a bug, it was my decision to do it that way, for me this is simply was the right way to go.

the question matters to me was not, how does groovy do it? it was how will users will use that functionality, does it matter for the users if only part of it exist.
And i'm sure for most users in most cases it does not matter at all, they are only interested if "c" exist and has a value (in your example), nothing else.
i saw a lot of variables checks in the past (with isdefined,parameterexists,structkeyExists,isNull,<cfparam> ...), but in nearly all cases it was about all or nothing. so the groovy behavior is simply not helping in most cases.

Micha










--
Did you find this reply useful? Help the Railo community and add it to the Railo Server wiki at https://github.com/getrailo/railo/wiki
---
You received this message because you are subscribed to the Google Groups "Railo" group.

For more options, visit https://groups.google.com/groups/opt_out.



--
/micha

Michael Offner CTO Railo Technologies GmbH
Reply all
Reply to author
Forward
0 new messages