> Le 13 janv. 2016 à 18:06, C. Scott Ananian <[email protected]> a écrit :
> 
> On Wed, May 21, 2014 at 8:33 AM, Claude Pache <[email protected] 
> <mailto:[email protected]>> wrote:
> 
> I have thought about the right semantics (and the issues) of the existential 
> operator.
> 
>     user.getPlan?().value?.score;
> 
> The intended semantics of `?` is that, whenever its LHS evaluates to `null` 
> or `undefined`,
> the evaluation of the whole expression (or subexpression) is interrupted and 
> return immediately `undefined`.
> In other word, it may be seen as an abrupt completion, as demonstrated by the 
> following expansion:
> 
>     (do {
>         let result = user           // user
>         result = result.getPlan // _.getPlan
>         if (result == null)         // _?
>             break                   // abrupt completion
>         result = result.call(user)  // _()
>         result = result.value       // _.value
>         if (result == null)         // _?
>             break                   // abrupt completion
>         result = result.score       // _.score
>     })
> 
> Now, it should be determined, whenever such an abrupt completion is 
> encountered during evaluation,
> in which cases it should propagate, and in which case it should be 
> transformed into a normal completion of value `undefined`.
> Roughly, property accesses and function calls should propagate it when it is 
> found on their LHS,
> and in all other cases it should be mutated it to 
> NormalCompletion(undefined). E.g.:
> 
>     (user.getPlan?().value?.score || 0).toFixed(2) // the `||` operator 
> interrupts the abrupt completion propagation
> 
> 
> Here is a simple strawman that illustrates how that idea could be implemented 
> in the spec.
> It has some known (and unknown) issues, but I think it gives a good idea of 
> the mechanism.
> And it resolves quite naturally the non-compositional issue of the original 
> strawman (see the remark at the end of the message).
> 
> The specification is patched as follows:
> 
> 6.2.2 The Completion Record Specification Type
> 
>     An additional value is allowed for the [[type]] field, besides normal, 
> break, continue, return, or throw; namely: failsoft.
> 
> 6.2.3.1 GetValue(V)
> 
> An additional parameter is added to that abstract operation:
> 
>     GetValue(V, propagateFailsoft = false)
> 
> If the second argument is absent, it is presumed to be false. An additional 
> step is prepended to the algorithm:
> 
> 0. If V is an abrupt completion of [[type]] failsoft and if propagateFailsoft 
> is false,
>     a. Let V be NormalCompletion(undefined).
> 
> 
> 12.3 Left-Hand-Side Expressions
> 
> The production of MemberExpression is expanded as follows:
> 
> FailsoftMark:
>     "?"
> 
> MemberExpression:
>     (...)
>     MemberExpression FailsoftMark
> 
> The runtime semantics is the following:
> 
> MemberExpression: MemberExpression FailsoftMark
> 
>     1. Let ref be the result of evaluating MemberExpression.
>     2. Let val be GetValue(ref, true).
>     3. ReturnIfAbrupt(val).
>     3. If val is null or undefined,
>         a. Return Completion([[type]]: failsoft, [[value]]: undefined, 
> [[target]]: empty).
>     4. Return val.
> 
> Here, there is an issue in expressions like `a.b?(c)`, because the correct 
> `this` value of the method call won't be able to be determined.
> This can be resolved by further suitable refinements.
> 
> Finally, in the algorithms involving LeftHandSideExpression's (section 12.3), 
> some calls to GetValue(...) are replaced by GetValue(..., true).
> They are:
> 
> Property Accessors
> 12.3.2.. Runtime Semantics: Evaluation
> MemberExpression : MemberExpression [ Expression ]
> Step 2. Let baseValue be GetValue(baseReference, true).
> 
> The new operator
> 12.3.3.1 Runtime Semantics: Evaluation
> NewExpression : new NewExpression
> Step 2. Let constructor be GetValue(ref, true).
> 
> ibid.
> MemberExpression : new MemberExpression Arguments
> Step 2. Let constructor be GetValue(ref, true).
> 
> Function Calls
> 12.3.4.2 Runtime Semantics: EvaluateCall
> Step 1. Let func be GetValue(ref, true).
> 
> In all other cases, a call to GetValue(...) will intercept a failsoft abrupt 
> completion and return `undefined`.
> 
> 
> A notable fact of that strawman is that the two following expressions are 
> equivalent:
> 
>     (a?.b).c
>     a?.b.c
> 
> because evaluating a ParenthesizedExpression does not apply GetValue(...) 
> (Section 12.2.10.4).
> 
> —Claude
> 
> Whatever happened to this proposal?  I'd love to see a proposal for the 
> existential operator continue to move ahead, and Claude's was the best one, 
> IMO.
>  --scott
>  

Since nobody seems to have taken this, I will submit a formal proposal for 
stage 0 very soon (before two weeks). 

With respect to the above old draft, my proposal will use a special Reference 
instead of a special abrupt completion (see [1]); but the basic idea remains 
the same: the essential difference is that the spec will propagate the special 
Reference at chosen points instead of catching the special abrupt completion 
everywhere else.

The exact syntax will remain open, as `?.` has some issues, and there are 
nonproblematic alternatives such as `.?` and `..`; but the semantics should be 
ok.

[1]: 
https://esdiscuss.org/topic/existential-operator-null-propagation-operator#content-42

—Claude

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to