#966 Truth and Nullability

msl Tue 9 Feb 2010

Hi All,

I'm writing some code that deals with user input where there are a range of possible combinations of values and find myself doing things like this quite a bit:

Str? a
Str? b
// Parse input
if (a == null && b == null) { // don't do anything }
if (a != null && b == null) { log.warn("b must be defined with a") }
if (a == null && b != null) { log.warn("a must be defined with b") }
if (a != null && b != null) { // do stuff }

I'm wondering whether this is a situation that other people find they're commonly bumping into with nullable types and whether there's a nice middle ground between "the only thing that's true/false is a Bool" (fantom) and "almost anything can be true/false if you know the rules" (python)?

In short, I'm wondering whether a null object should be considered false? With the examples above:

Str? a
Str? b
// Parse input
if (!a && !b) { // don't do anything }
if (a && !b) { log.warn("b must be defined with a") }
if (!a && b) { log.warn("a must be defined with b") }
if (a && b) { // do stuff }

I guess the edge case here is handling of Bool? but I can't think of a scenario (in my current mindset) where this handling would go against the desired logic (and if you do need a true/false/null three-way check you can still do so):

Bool? b
if (b == null) {
  // b is null
} else if (b) {
  // b is not null and true
} else if (!b) {
  // b is not null and false
}

Martin

tactics Tue 9 Feb 2010

I find it natural to accept null as false in a condition. However, it does create a weird issue when you're dealing with the Bool? type.

ivan Tue 9 Feb 2010

Probably the question is how to interpret !a, is it a == false or a != true

However in the particular case above I'd write something like this

switch([a == null, b == null])
{
  case [true, true]: {//don't do anything}
  case [true, false]: {//warn about a}
  case [false, true]: {//warn about b}
  case [false, false]: {//do work}
}

msl Tue 9 Feb 2010

That's very cool. I need to get my head out of java-switch-thinking...

brian Tue 9 Feb 2010

I definitely think we want to keep truth conditions limited to Bool. If there was one thing we learned moving from C to Java, it was that not there was huge advantages in static typing by not allowing any old expression to be used in conditions such as:

if (a = b)

My personal experience is that now I tend to use things like ?: more often rather than explicit null checks.

msl Wed 10 Feb 2010

My personal experience is that now I tend to use things like ?: more often rather than explicit null checks.

I did consider the elvis operator and null safe calls but I couldn't come up with a "nice" way to express the same conditions... About the best I could come up with is something like (written on my phone, so not sure if it actually works):

if (a ?: b ?: "" == "") // do nothing
else if (a ?: b == b)  // warn about a being null
else if (b ?: a == a)  // warn about a being null
else // do stuff

The behavior of this is dependent on "" being an invalid value for a/b... if either of those values could be "" then the first case incorrectly (for the desired logic - correctly for what's written) evaluates to true?

Any suggestions for a better approach?

qualidafial Fri 12 Feb 2010

I think it would be useful to have a short expression for evaluating whether an object is non-null. Something like foo? evaluating to foo != null would be nice, but that syntax might be hard or impossible to distinguish from ternary expressions.

msl Fri 12 Feb 2010

I like the consistency with type definitions:

Str? foo
if (foo?) {
 // don't use foo
}

but that's an opinion given with no consideration whatsoever to how it might effect the language :)

Akcelisto Fri 12 Feb 2010

May be:

foo!? for foo != null

foo=? for foo == null

helium Fri 12 Feb 2010

foo? looks OK. You can negate boolean values using the ! operator, so !foo? would be true if foo is null. No need to invent new operators that look like an interrobang ‽

KevinKelley Fri 12 Feb 2010

Actually sounds pretty cool... foo? should mean "is there a foo", though, not "is foo null", imo.

Seems like this is an analog to the if statement with no else branch. We have ?: as an expression-analog to the if...else statement, but we don't have an expression for just the if.

helium Fri 12 Feb 2010

@KevinKelley: ? analog to ?: to test for "if not null"?

x := y ? z

x is z if y is not null otherwise x is null? When would that be useful?

qualidafial Fri 12 Feb 2010

That's not what I'm suggesting. What I meant is to make foo? shorthand for foo != null, since null checks are such a common pattern in code.

andy Fri 12 Feb 2010

I like the ideas in this thread. However I think if you added foo? - it would have to resolve to foo == null - to be consistent with the type system:

Str? foo  // def to null
if (foo?) echo("foo is null)
if (!foo?) echo("foo is not null")

I admit the common case doesn't look as nice - but I think consistency and expectation trump that.

KevinKelley Fri 12 Feb 2010

When would that be useful?

I guess, when the z part needs to use the y but can't handle a null:

x := y? z(y)

instead of

x := (y!=null)? z(y) : null

The null-safe operators and elvis cut out a lot of the need for if (x!=null), but they don't cover every situation.

KevinKelley Fri 12 Feb 2010

Just for grins, I grepped 605 occurrences of "!= *null" in my working fan dir, and 702 in the 1.0.51 Fantom src.

tcolar Fri 12 Feb 2010

Since i'm working on a fan parser)for the IDE) right now and there is already a lot of difficult thing to deal with when it comes to ? i would prefer this not to happen.

  1. How will the parser know whether str? is a nullable type or an expression of whether the str variable is null
  2. I think it could also get confused big time with ternary expressions if the expression after y? contains a column (map)

Syntaxic sugar is nice, until you write a parser :)

brian Sat 13 Feb 2010

I think we are about wrapped up for language changes for now (other than maybe the using syntax for scripts), because I want to give guys like tcolar a chance to get their IDEs caught up and let things settle down.

That doesn't mean this isn't a good discussion for something we add to 1.1. I am total agreement that there is a huge amount of code that uses these constructs:

if (x == null) ...
if (x != null) ...

I would definitely like to have a syntax for this common case. However, note this tends to be a statement/flow control problem, not an expression problem (which the ?: tackles). So I'd more inclined to use some keyword or combo with if that was easy to parse:

ifxxx (x) ....
if? (x) ...
if ?(x) ...
if (x)? ...

DanielFath Sat 13 Feb 2010

I have a question. Is if (x)? same as

if ((foo)?) //1st case
if (foo)?   //2nd case

Of the bat the first problem I see is how do you combine these examples with some other boolean expression (i.e. how do you write if (x==null && y<z))

Login or Signup to reply.