Sentinel
Language: Undefined
The value undefined
is a special value representing undefined behavior
or an unknown value.
Undefined is not an error because there are situations where the undefined value can be safely ignored and the language also provides construts for recovering from an undefined value.
The undefined value can be created manually with undefined
. In most cases,
undefined is created by accessing a non-existent list element or value.
The undefined value is created in a number of other circumstances. The documentation
will note when an undefined value may be created.
Almost any operation with undefined
results in undefined
. For example,
performing math on undefined, attempting to call a function that is undefined,
etc.
Main and Undefined
If the value undefined
is returned from the top-level main
rule, then
the policy is considered false
. However, the runtime provides mechanisms
for the host application to determine the policy failure was caused by
an undefined value and report that to the user.
The main
rule returning the undefined value should be considered a logical
error in most cases and should probably be corrected by the policy writer.
Debugging Undefined
When an undefined
value is first created (either explicitly or implicitly),
the runtime will record the position where the undefined was created. This
location can be used to find logic that could be erroneous.
Boolean Logic and Undefined
Boolean logic is one way to safely recover from undefined
. If boolean
logic can safely determine a result despite an undefined value, that result
will be returned.
For example: undefined or true
will result in true
, because no matter
what actual value undefined
could've been if the policy behaved properly,
the boolean expression would still be true.
Another scenario where undefined
can be safely ignored is short-circuit
logic with and
. false and undefined
will result in false
.
The full table of logical operations on undefined
is below:
undefined or true = true
undefined or false = undefined
undefined or undefined = undefined
undefined and true = undefined
undefined and false = undefined
undefined and undefined = undefined
undefined xor true = undefined
undefined xor false = undefined
undefined xor undefined = undefined
// Short-circuit examples
false or true or undefined = true
false or undefined or true = true
true and false and undefined = false
true and undefined and false = undefined
Else Expressions
The else
expression allows explicit recovery from undefined and is useful
for setting default values.
else
is an operator where the left and right hand side are values. If the
left-hand value is undefined
, the right-hand value is returned. Otherwise,
the left-hand value is returned.
Examples:
foo() else 42
foo.bar else ""
config["bad-key"] else "default"
// In more complex scenarios
foo() else 42 == 12
a = config.value else "default"