Not operator on null

Sorry if this is the wrong place to ask or if this has come up before. I didn't find it in the forum search, and it's not really a bug, more of a feature request.

Considering the following code is valid (and doesn't execute, as expected):
var item=null;
if(item) { ... }


It seems logical that I should be able to do the following:
var item=null;
if(!item) { ... }


Which instead throws an UnexpectedTypeException.
Is the usage of the not operator on a null to return a true something that could be considered?

Thanks,
  • I feel that this is a case where your code should do exactly what you mean. For example...

    var item = null;
    if (item != null) {
    // do something
    }

    if (item == null) {
    // do something
    }


    The reason is that the check if (item) will return true if item is non-null, but only if it is also not also an integral type (Boolean, Number, Long) with a zero value. I'm not familiar with all of the languages that MonkeyC is based on, but this is unusual behavior. It is inconsistent behavior across types, which seems to indicate some sort of bug. Personally, I think it makes more sense to disallow using a null value in a conditional expression (including for/while/do loop condition), than it does to add support for the not operator.

    If you only want a null check, you should be explicit and check against null. If you want to know if the value is null or is an integral type with the value zero, you could use the simple check, but then you'd be relying on someone else (maybe even yourself) remembering this weird behavior where you could have just been explicit about it in the first place.
  • Here is an example of the weirdness I mentioned above.

    function f(item) {
    if (item) {
    return true;
    }
    else {
    return false;
    }
    }

    f(null); // returns false

    f(false); // returns false
    f(0); // returns false
    f(0l); // returns false
    f(0.0); // returns true, why?
    f(0.0d); // returns true, why?

    f(true); // returns true
    f(1); // returns true
    f(1l); // returns true
    f(1.0); // returns true
    f(1.0d); // returns true
  • Returning false in the f(null) case is consistent with similar languages like Python. For example, this will print "False":

    myVar = None
    if(myVar):
    print "True"
    else:
    print "False"


    The same goes for a Ruby equivalent, and both will evaluate the expression to true if you do an "if !myVar" kind of check. This is a case where I think you're both right--we should do as the OP suggests for consistency, and we need to make sure some of those other cases with zero float and double values work consistently, too. I tend to agree with Travis that checking against null is better practice since it's easier to read and more explicitly stated. I seem to remember a ticket related to this at one point, but I'm not able to find it at the moment. I'll create a new ticket to capture this and see if we can get this cleaned up.
  • I have always worked on the programming principle that null is neither true nor false so any test on a null value will always fail.
  • I have always worked on the programming principle that null is neither true nor false so any test on a null value will always fail.


    Same here. Null isn't a boolean condition by itself as it's really neither. ==null or !=null makes more sense to me, and adds to the readability of code as to what you're testing for.

    You could do something like "if(x instanceof Number)", and it would work, but is less readable to me.
  • ...null is neither true nor false...

    Yes, that's true. In fact, we had a similar discussion this week during our team review. We just need to decide whether we treat null simply as null (neither true nor false), or follow the precedent set by other, similar languages. We're checking a few under-the-hood items to make sure everything works consistently, and then a decision will be made.
  • As a purist, I'd vote to leave null neither true nor false, but review why, in Travis's example, f(0.0) and f(0.0d) return true.
    Ahh! the joys of an un-typed language.;)