IsDefined() function and “catch” operator for AQL

Whenever an expression encounters an error and yields no result, this infects the outer expression it is embedded in — any access to an undefined property voids the whole computation for the current input. There currently is only one way to work around this: CASE conditions “catch” the error and try the next condition instead of erroring out immediately. In order to use this facility, the user must formulate a boolean condition to check the data, though.

CASE _.my_property.some_string ≥ '' => _.my_property.x[3]
CASE TRUE => 'replacement value'
ENDCASE

We solve the last part by adding the function IsDefined(<expr>), which takes a single argument and evaluates to TRUE if the expression yields a value and FALSE otherwise. With this, one could write

CASE IsDefined(_.my_property) => _.my_property.x[3]
CASE TRUE => 'replacement value'
ENDCASE

This is an improvement in that the incidental complexity of figuring out a suitable boolean condition is taken away.

One common use of this pattern is to include default values in the query in case the data are incomplete (e.g. from an old version). Here, the condition is usually that the desired value should exist, so we introduce the shorthand notation

_.desired // 'replacement'

which is equivalent to

CASE IsDefined(_.desired) => _.desired
CASE TRUE => 'replacement'
ENDCASE

Formally, // is a binary operator with the lowest precedence.

Definitely a useful feature from my PoV.
However, I find using // as shorthand confusing, it looks like a comment to me.
I’d suggest using ?? or ?: as known from null(-ish) coalescing / elvis operators in many languages*.

WDYT?

* // actually seems to be the Perl way of saying defined-or, but who knows / wants to know Perl these days?

The pointer to nullish-coalescing ?? makes an interesting point: it treats NULL also as non-satisfactory, not only undefined inputs. This seems like a very useful feature because producing a non-satisfactory value for the left-hand side right now requires some gymnastics like ([])[0] — NULL would be so much more obvious.

I think we should go with that proposal. ?: is too close to the ternary operator from C-like language, I’d like to avoid that.

1 Like