Most programming languages have a null value which is used to indicate the absence of a valid value. Lisp and Ruby have nil, Python has None, Perl has undef, and so on.

LotusScript is a bit different. It’s modeled on Microsoft’s Visual BASIC, a decision that probably seemed sensible in the pre-JavaScript early 90s when Lotus picked a scripting language for Notes. As a result, LotusScript has three different null values. This can lead to some unexpected run-time crashes.

The first null value is Empty. This is the value of a variable of type Variant that has not yet had a value assigned. You can’t directly assign something to be Empty, but you can do something like this:

Dim empty As Variant
x = empty ' x is now empty too

You can’t make non-Variant variables Empty; you’ll get a run-time error if you try.

The second null value is Null. It’s also used with Variants. Whereas Empty is the default null value of a Variant, Null is the usual null value resulting from an assignment expression. That is, it’s the null value you would typically return from a function that returns a Variant, in order to indicate an error, exception or missing value to the caller. (Though as noted above, you could return Empty if you really wanted to.)

Then there’s the third null value: Nothing. Nothing is primarily used with non-Variant variables. For example, NotesView.GetDocumentByKey will return Nothing if the document isn’t found. Also, if you declare an object variable but don’t initialize it, it is set to Nothing by default. Unlike Empty, however, you can directly assign variables to have a value of Nothing. So basically, it plays the role of both Null and Empty, but for object variables.

But while Nothing is primarily used with non-Variant types, you can also assign Notes objects to Variant variables, which means that Variants can end up being Nothing, depending on your code. Which led to my discovering a couple of interesting pitfalls.

To make life exciting, each kind of null in LotusScript has a different way of testing for it. Isnull and Isempty test for Null and Empty values respectively; but for Nothing, the syntax to check is expr Is Nothing.

(Why? My guess is that when object orientation was bolted onto BASIC, the developers at Microsoft decided to provide for null object references by creating a special predefined object called Nothing, because that was the easiest thing to code. Probably nobody cared that the language already had Null and Empty. Similarly, adding a new “Is” operator was probably easier than making the existing comparison operator work on objects.)

Not only is the syntax different for testing Nothing values, the behavior is different too. While Isnull and Isempty are safe when passed Nothing, expr Is Nothing will crash with a run-time error if the expression is Null or Empty. So if you have a Variant which may contain Nothing as well as either Empty or Null, you need to test it with Isnull and/or Isempty before testing for Nothing.

A second pitfall is that you can print Null and Empty values — they display as “Null” and "" (empty string) respectively — but a Nothing value will cause a run-time error if you try to print it.

The two pitfalls can combine, of course. If you want to print or log your Variant’s value for debugging purposes, you need to check for Nothing in order to avoid a crash when printing; however, that means you need to check for Null and Empty first, to avoid having the check for Nothing crash. So you end up with:

If Isnull(v) Or Isempty(v) Then
  Print v
Elseif v Is Nothing Then
  Print "v is Nothing"
Else
  Print v
End If

Here’s a summary:

Null valueApplies toPurposeTest for it usingOutputs as
EmptyVariantsValue of uninitialized VariantIsEmpty(expr)""
NullVariantsIndicates an error, exception or missing valueIsnull(expr) or expr = Null“Null”
NothingVariants or object variablesUnitialized object, error, exception or missing valueexpr Is NothingRun-time error

On the bright side, it could be worse, as Visual BASIC has four more null values to worry about: Missing, vbNullString, vbNull, and vbNullChar.