Optional types
In SPL, an optional type is used when a variable or attribute might have no data value associated with it because the value is unavailable or unknown. When there is no data value for a variable or attribute, and an optional type is used, the value of that variable or attribute can be set to null.
Optional types are composite types, along with tuple and collection types, and are parameterized as such using the underlying type. The underlying type is the type of the data value when the variable or attribute has an associated data value.
Use the form optional<T> to declare variables or attributes in SPL that can have either a null value or a value of the underlying type T. For example, you can declare an optional int32 integer in a stream, list, or tuple, as follows:
stream<int32 i, optional<int32> j> Src = MySource() {}
mutable list<optional<int32>> myList;
type T = tuple<int32 i, optional<int32> j>;
A null value has a literal representation for every type that can express a literal value. The characters null represent a null value.
tuple<int32 i, optional<int32> j> t = { 1, null };
The following example declares and initializes a mutable integer variable to null:
mutable option<int32> i = null;
You can
assign a null value to an optional variable or attribute that has had a
non-null value:mutable optional<int32> i = 5;
i = null;
if (var == null) { }
Default initialization
When an operator returns a tuple that is default initialized, for example, a Beacon operator without an output clause, tuple attributes are initialized with their default values. The default value for an attribute of optional type is null.
Value assignment
optional<int32> i = 42;
or
optional<int32> j = i;
The unwrap operator is used to access the non-null value of an optional type for the purposes of assignment to a non-optional type. For example:
int32 k = j!;
The unwrap operator will cause a runtime error if the value of j is null.
The unwrap-or-else operator is used to assign from an optional type to a non-optional type when the value of the optional type might be null.
In the following example, if the value of j is null, k is assigned the default value of 4:int32 k = j ?: 4;
Automatic promotions
- Literal null
- null is automatically promoted to optional<T> if the
type T can be determined. For example:
optional<int32> i = null;In this case the type can be determined, and the literal null is promoted to type optional<int32>.
- Expression with optional and non-optional types
- Another case for promotion is when an optional type and a non-optional type appear in an
expression. For example:
In this case the literal 5, which is of type int32, is automatically promoted to optional<int32>. Another example:optional<int32> i = 5;
In this case, 5 is promoted to the type optional<int32>.if (i == 5) { } // i is of type optional<int32> - In the case of list, map, and set literals, promotions occur as necessary on the list, map or set items and the overall resulting literal. For example:
mutable optional<map<optional<int32>, optional<rstring>> m1 = null; m1 = {1:"a"}; // legal
stream<optional<int32> i, optional<int32> j> A = myOp() {
param
p1: null;
p2: (optional<int32>) null;
}
..
composite myOp(output Out) {
param
expression<optional<int32>> $p1;
expression $p2;
graph
stream<Types> Out = Custom() {
logic onProcess:
submit({i=$p1, j=$p2},Out);
}
}
Operators for optional types
- isPresent
- The isPresent operator, (??) checks if a variable or attribute of optional type
is non-null. The isPresent operator returns true if the variable or attribute of
optional type is non-null and false if the variable or attribute is
null. For example:
if (var??) { } - uwrap
- The unwrap operator (!) accesses the data value of an optional type when the
value of the optional type is not null. For
example:
When the value of the optional type is null, you will get a runtime exception.optional<int32> x = someFunctionThatReturnsAnOptional(); int32 y = x!; - unwrapOrElse
- The unwrapOrElse (?:) operator gets the data value of an optional type if the
value is not null. For
example:
int32 i = optional_var ?: 0;.The value after the ?: acts as a default data value that is used when the value of the optional type is null.
You can use these operators with expressions of non-optional type. The isPresent operator returns true for non-optional type expressions. The unwwrap operator returns the expression provided for non-optional type expressions. The unwrapOrElse operator returns the expression provided when given a non-optional type expression and never uses the default value.