The New Xojo If() Operator

Xojo 2014 Release 1 introduced a new conditional operator: if(). Although it looks like a function, it is not. It is an operator, and behaves in a very special way.

IIF Functions

Many developers, have kept a function called iif in their toolbox of reusable code. It typically looks something like this:

Function IIF (Test As Boolean, TrueValue As Variant, FalseValue As Variant) As Variant
  If Test Then
    Return TrueValue
  Else
    Return FalseValue
  End If
End Function

This makes it very handy to write something like:

Dim Message As String = "You have " + iif(NumItems = 1, "1 item", Str(NumItems) + " items") + " in queue."

Nothing we couldn't do with a few more lines of code:

Dim Message As String = "You have "
If NumItems = 1 Then
  Message = Message + "1 item"
Else
  Message = Message + Str(NumItems) + " items"
End If
Message = Message + " in queue."

So we get it done in 1 line instead of 7 lines. Not a deal breaker by any means, but there are certainly times when this behavior is useful.

The Problem With IIF In Xojo

When calling a function, all possible parameters must be evaluated before the function can begin. In this example, the function receives True, "1 item", and "X items". Not a big deal in this example, but consider the following usage:

Function CellValue (Index As Integer) As String
  Return IIF(Index <= UBound(Cells) And Index > -1, Cells(Index), "")
End Function

The idea is to return the value from Cells(Index) only if the index is a valid value. With such a function, Cells(Index) will always be evaulated, so if passing in an invalid Index, an OutOfBoundsException will be thrown and thus defeating the purpose entirely.

The other problem is casting. The possible responses are converted to variants, and the function returns a variant. Variants, although very helpful at times, are also very evil and prevent the compiler from doing its job. Consider this code:

Dim Message As String = IIF(TextField1.Text <> "", TextField1, "No Value")

This will compile without error, but it'll produce an exception at runtime. Of course it is a typo, the second parameter should have been TextField1.Text, but that's entirely the point. The compiler should have caught that typo.

The Solution

The new if() operator solves all these problems. It behaves exactly like the traditional If construct, but allows for assignment, something the If construct cannot do.

Most importantly, input parameters are not evaluated until needed. So if the boolean evaluates to true, the false value will never be evaluated at all. This means our CellValue example from earlier will work as intended:

Function CellValue (Index As Integer) As String
  Return if(Index <= UBound(Cells) And Index > -1, Cells(Index), "")
End Function

The if() operator also checks types. The type it returns is the lowest common denominator of the two return values. If there is nothing common between the two, a compiler error is thrown. And then the value returned must also be assignable to whatever variable it is being assigned to. So it would have caught our TextField1 typo from earlier.

Conclusion

Overall, the new if() operator has its places where it's useful. Not only can you compact some lengthy parts of code but it also helps in replacing your custom IIF function or porting from languages that already use IIF.