On 21 May 2014 14:33, Claude Pache <claude.pa...@gmail.com> 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
Drive-by comment: This would break the switch or loop statement surrounding the do-expression (or be an error if there isn't any). You need to wrap the statements into a labelled block and break that. /Andreas > 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 > > > > > > _______________________________________________ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss _______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss