Proposal: The Conditional Fail and Recover Operators; or: a more generic Existential Operator

Claude Pache claude.pache at
Tue May 27 00:03:20 PDT 2014

Since nobody gave their advice, I'll give my own one :-)

The particular case of the Existential Operator (conditional property access and conditional method call) is probably the more usual one.
The case that I 've come across, which is maybe the more common one not covered by the Existential Operator, 
consists of using a static method, but thinking of it as if it were a method of its first argument. 
Some syntactic sugar could help to both replace it to the correct position (at the right side of the object)
and integrate it well with the Existential Operator. 
Thus, I think we could explore rather that direction.

Ok, I stop my monologue here...


Le 23 mai 2014 à 09:18, Claude Pache <claude.pache at> a écrit :

> Le 22 mai 2014 à 23:58, Claude Pache <claude.pache at> a écrit :
>> Hi,
>> Today, I came to a case where I wanted to grab a reference to some getter of the DOM,
>> but to not fail if it doesn't exists:
>> ```javascript
>> try {
>>   originalElementsGetter = Object.getOwnPropertyDescriptor(window.HTMLFormElement.prototype, 'elements').get
>> }
>> catch(e) {
>>   originalElementsGetter = undefined
>> }
>> ```
>> (If you are curious: the context is monkey-patching `<form>.elements`, so that it includes
>> the `<output>` elements of the form, for I've just discovered that IE forgets to include them.)
>> This seems to be a typical case for the Existential Operator (?.) we spoke recently about
>> (although, in my precise case, a try/catch does the trick).
>> However, the Existential Operator works only on properties and methods:
>> ```javascript
>> // Bad: if window.HTMLFormElement?.prototype is undefined, Object.getOwnPropertyDescriptor will protest loudly.
>> originalElementsGetter = Object.getOwnPropertyDescriptor(window.HTMLFormElement?.prototype, 'elements')?.get
>> // Here is what I could use:
>> Object.defineProperty(Object.prototype, '$getOwnPropertyDescriptor', {
>>   value: function(prop) { return Object.getOwnPropertyDescriptor(this, prop) }
>> , writable: true
>> , configurable: true
>> })
>> oldElementsGetter = window.HTMLFormElement?.prototype?.$getOwnPropertyDescriptor('elements')?.get
>> ```
>> Can we do better?
>> I want to propose a mechanism that can simply express the following
>> (only partially fulfilled by the Existential Operator):
>> 1. check for nully (null or undefined) values at precise spots of an expression being evaluated;
>> 2. if a nully is found, stop the evaluation of the entire current (sub)expression, and yield undefined;
>> 3. or, instead of yielding undefined, provide an alternate value;
>> 4. and be able to determine precisely what "the current subexpression" of point 2 means.
>> So, let's introduce the Conditional Fail Operator (`??`), and, its counterpart, the Recover Operator (`!!`).
>> (You could think of them as a throw/catch-like mechanism, or, better, as a break/block-like mechanism.)
>> For the sake of illustration, I have artificially lengthen my original example:
>> ```javascript
>> originalElementsGetter = Object.getOwnPropertyDescriptor(window.HTMLFormElement??.prototype??, 'elements')??.get??
>>                         !! Object.getOwnPropertyDescriptor(window.HTMLElement??.prototype??, 'elements')??.get??
>>                         !! Object.getOwnPropertyDescriptor(window.Element??.prototype??, 'elements')??.get
>> ```
>> The semantics are the following:
>> * `??` is a unary operator that is used as suffix. If its operand is nully (null or undefined),
>>   the evaluation of a certain expression (more precisely defined below) that it is part of, fails immediately.
>>   Otherwise, the operand is just returned as is.
>> * `!!` is a short-circuiting binary operator. It evaluates its LHS.
>>   If the evaluation is not interrupted by a `??`, it returns the result.
>>   But if the evaluation is interrupted by a `??`, it evaluates its RHS and returns the result.
>> * For any assignement operator (`=`, `+=`, etc.), if the evaluation of its RHS is interrupted by a `??`,
>>   the RHS is replaced by `undefined` and the assignment is performed normally.
>> * All other operators and function calls are transparent to the failure signal send by `??`
>>   (you have to stop it by an explicit `!!`).
> I see a nasty footgun in the last two bullets, in case someone refactors from ` = baz??` to `fooMap.set('bar', baz??)`, for the latter will fail silently.
> But we do want function calls to be transparent to  `??`-failure signals, as it can seen in my original example.
> The best alternative I can see, is the following:
> * All operators (excluding `!!`, of course, but including assignments) and function calls are transparent to failure signals.
> * If a failure signal remains uncaught, an error is thrown (and this condition may even be statically determined and produce an early error).
>    This will catch (!) early failed-assignment bugs, and force the programmer to be more explicit.
> With this amendment, my example must be completed with a final `!! undefined`:
> ```javascript
> originalElementsGetter = Object.getOwnPropertyDescriptor(window.HTMLFormElement??.prototype??, 'elements')??.get??
>                         !! Object.getOwnPropertyDescriptor(window.HTMLElement??.prototype??, 'elements')??.get??
>                         !! Object.getOwnPropertyDescriptor(window.Element??.prototype??, 'elements')??.get??
>                         !! undefined
> ```
> —Claude
>> As I have shown in [1], it seems relatively easy to spec such a behaviour using a custom Abrupt Completion.
>> The proposed spec needs to be refined in order to avoid precocious GetValue(...) calls,
>> but I am able to write a complete strawman in case there is interest.
>> WDYT?
>> —Claude
>> [1]

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list