Chapter 12. Missing values

Table of Contents

Uninitialized Variables
Out-Of-Bounds Indexing
Outer Joins
Empty Functions
Operator Failures
Data Import

In Rax every type has an associated missing value that is to be used when an expression fails to produce a valid value. For example, by default, dividing by zero yields 0 in Rax. Therefore, the above example code can be simplified while producing the same result, like so:

    avg := fold[/average(.#1/.#2)] BigTable;
       

Since 0 might not be a suitable value for a divide-by-zero failure for all expressions, Rax features a meta operator %missing to change missing values. In the example below the division-by-zero yields a billion billion:

    %missing & 1.0e18;
    big := 4.0 / 0;
       

Note that, in general, it is best to have as few as possible %missing instructions in a program and they should cluster at the top.

Each type in Rax has its own initial missing value. The table below shows those initial missing values per type:

Table 12.1. Initial Missing Values for Rax Types

TypeInitial Missing Value
#0
&0.0
$""
?false
@2000-01-01T00:00:00
^P0D
~P0D
|2000-01-01T00:00:00/PT0S
[...]A tuple with each field containing the missing value for its type, recursively.
{...}Empty set.
f()Calling an empty function returns the missing value for the output type of the function.


There are five categories of expressions where missing values can appear. Below they will be discussed one by one.

Uninitialized Variables

In Rax, variables can be declared without an initial assignment. In this case, they are initialized with the current missing value as demonstrated by the example code below:

    &: r;
    `print r;                 // Output: 0.0;
    ?: a_boolean;
    `print a_boolean;         // Output: false
    #: a_number;
    `print a_number;          // Output: 0
       

Below an example where the %missing meta instruction is used to change a missing value for reals:

    %missing & 1.0;
    &: p;
    `print p;                 // Output: 1.0;
       

Missing values for compound values (i.e., tuples and ordered sets) can not be set. Tuple types will always have a missing value equal to the tuple of missing values of the field types. Ordered set will always have the empty set as missing value:

    [#, ^]: a_tuple;
    `print a_tuple;   // Output: [0, P0D]

    // Changing some missing value defaults:
    %missing @ "1900-01-01";
    %missing & -1.0;
    %missing # 33;

    [&,@,#]: T;   // Define a tuple of a real, time and number.
    `print T;         // Will print [-1, 1900-01-01T00:00:00, 33];
    {\T}: A;          // Define a table with a real, time and number.
    `print A;         // Will print an empty table/set;
       

As the above example shows, missing values for tuples can be set indirectly by setting the missing values for its field types. There is no way to change the missing value for sets. Therefore, if the empty set is a valid value of an expression that can also fail, preemptive checking is needed to distinguish a 'failure' empty set from a 'valid' empty set.