The result of evaluating a CEL expression whose outcome depends on inputs
that are not known, in the spirit of cel-go's types.Unknown.
An unknown carries the set of entries it depends on. Each entry pairs an attribute with the opaque reason the caller supplied:
{:var, name}— a top-level variable bound to{:unknown, reason}.{:call, function, expr_id}— a custom function call that returned{:unknown, reason}.
Bind a variable as unknown by passing {:unknown, reason} (or an existing
CEL.Unknown, to forward one result into another evaluation):
{:unknown, unknown} =
CEL.eval("x < 30 && y > 1", %{x: {:unknown, :timeout}, y: {:unknown, :missing}}, env)
CEL.Unknown.entries(unknown)
#=> [{{:var, "x"}, :timeout}, {{:var, "y"}, :missing}]Operators that can decide their result without an input do so: false && x is false and true || x is true. Every other operation that reads
an unknown returns an unknown, merging the entries of all unknown operands.
When an operand of a strict operation is an error, the error wins, because
the outcome no longer depends on the unknown inputs. In &&, || and
comprehensions an unknown wins over an error, because a known input could
still decide the result.