The Existential Operator
Le 20 mai 2014 à 05:50, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a écrit :
Hi,
(I remember, I mentioned this couple of years ago, but not sure about whether it was considered, etc)
Will the "Existential Operator" for properly accessors be something interesting to consider for ES7 spec? Currently CoffeeScript uses it well.
var street = user.address?.street;
The
street
is either the value of theuser.address.street
if theaddress
property exists (or even if it's an object), ornull
/undefined
otherwise.This (roughly) to contrast to:
var street = user.address && user.address.street;
(the chain can be longer in many cases).
The same goes with methods:
var score = user.getPlan?().value?.score;
If potentially it could be interesting for ES7, I'll be glad helping with the proposal, grammar and algorithm (unless it was considered previously, and decided that it's not for ES for some reason).
P.S.: I tried to solve this issue using default values of destructuring assignment, but it doesn't help actually.
Dmitry
Question: What is the semantics of the following:
a?.b.c
Is it the same thing as
(a?.b).c
(a && a.b).c
or the same thing as:
a && a.b.c
(For the sake of the argument, just ignore the distinction between "falsy" and "null/undefined".) If it is the second option, I fear that the semantics of the so-called "existential operator" is more complicated than just an "operator".
I think the current use of this operator will only make sense if the operator interrupts the whole sentence so
a?.b.c
Will be the same as
a && a.b.c
And
a?().b?.c?.d
Will be same as
a && (x = a(), x.b && (x.b.c && x.b.c.d))
A. Matías Quezada Senior Javascript Developer amatiasq at gmail.com
2014-05-20 11:31 GMT+02:00 Claude Pache <claude.pache at gmail.com>:
It might be worthwhile keeping an eye on the C# language discussion on the same operator - roslyn.codeplex.com/discussions/540883
From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of A Matías Quezada Sent: Tuesday, 20 May 2014 7:56 PM To: Claude Pache Cc: es-discuss Subject: Re: The Existential Operator
I think the current use of this operator will only make sense if the operator interrupts the whole sentence so
a?.b.c
Will be the same as
a && a.b.c
And
a?().b?.c?.d
Will be same as
a && (x = a(), x.b && (x.b.c && x.b.c.d))
A. Matías Quezada
Senior Javascript Developer
amatiasq at gmail.com <mailto:amatiasq at gmail.com>
2014-05-20 11:31 GMT+02:00 Claude Pache <claude.pache at gmail.com <mailto:claude.pache at gmail.com> >:
Le 20 mai 2014 à 05:50, Dmitry Soshnikov <dmitry.soshnikov at gmail.com <mailto:dmitry.soshnikov at gmail.com> > a écrit :
Hi,
(I remember, I mentioned this couple of years ago, but not sure about whether it was considered, etc)
Will the "Existential Operator" for properly accessors be something interesting to consider for ES7 spec? Currently CoffeeScript uses it well.
var street = user.address?.street;
The
street
is either the value of theuser.address.street
if theaddress
property exists (or even if it's an object), ornull
/undefined
otherwise.This (roughly) to contrast to:
var street = user.address && user.address.street;
(the chain can be longer in many cases).
The same goes with methods:
var score = user.getPlan?().value?.score;
If potentially it could be interesting for ES7, I'll be glad helping with the proposal, grammar and algorithm (unless it was considered previously, and decided that it's not for ES for some reason).
P.S.: I tried to solve this issue using default values of destructuring assignment, but it doesn't help actually.
Dmitry
Question: What is the semantics of the following:
a?.b.c
Is it the same thing as
(a?.b).c
(a && a.b).c
or the same thing as:
a && a.b.c
(For the sake of the argument, just ignore the distinction between "falsy" and "null/undefined".) If it is the second option, I fear that the semantics of the so-called "existential operator" is more complicated than just an "operator".
Claude Pache,
I had to read up on this existential operator to realize your question. In your example the variable 'a' is the target/operand of the existential operator. If 'a' isn't null or undefined then the result will be the result that you'd expect had you not used the operator, assuming theres not a TypeError in the expression. Here I choose to define an operator as a shorthand function of which I don't find overly complicated.
function example() { If (a !== null && a !== void(0)) return a; return void(0); }
If 'a' is undefined...
var a = void(0); example(a).b.c
Would normally throw but with the existential operator...
var result = a?.b.c
Does not.
result === void(0) // true
Another thought.
var a = {};
var result = a?.b.c;
Will throw because there can be no property 'c' on undefined.
var result = a?.b?.c; <-- Awesome semantics!
And of course: result === void(0) // true
Oh, one shouldn't ignore the difference between falsy and undefined. Implementing this in terms of falsyness will end up breaking someNumber?.toString() given a zero or someString?.length given an empty string.
Andri
Dmitry Soshnikov wrote:
Will the "Existential Operator" for properly accessors be something interesting to consider for ES7 spec? Currently CoffeeScript uses it well.
Please see
esdiscuss.org/topic/sept-18-tc39-meeting-notes#content-2
and find "ARB: This is non-compositional". Citing text for reader convenience:
Existential Operator (strawman discussion)
(Presented by Brendan Eich, Mozilla)
Significant desire include a null and undefined check in syntax/operator form (a la coffeescipt)
| o = {} r = o?.p.q.r r = o?.p?.q.r |
Mixed discussion about the needs and use cases as they apply to coffeescript code.
ARB: This is non-compositional
| o = {} r = o?.p.q.r r = (o?.p).q.r r = o?.p.q.r() |
Results in…
| var o, r; o = {}; r = o != null ? o.p.q.r : void 0; r = (o != null ? o.p : void 0).q.r; r = o != null ? o.p.q.r() : void 0; |
Non-starter.
DH: Why not an operator that needs to be explicit?
| o?.p?.q?.r |
LH: Why would you ever even use it on the first?
BE: Forget all of the problems with coffeescript's impl, the need exists.
YK: In the common cases, where it works, it works well. Where it doesn't, it falls apart unexpectedly.
WH: What about other contexts such as p?[x], p?.q[x], and p?(x) ? [Note that grammar problems arise for some of those.]
General agreement.
Conclusion/Resolution Seems useful, but not now. Semantics are unclear
The notes ended a bit too optimistically in my view! "Non-starter".
Woah! :) 2012 -- so I correctly recalled "couple of years ago". Thanks, glad it was discussed in detail.
On Tue, May 20, 2014 at 9:36 AM, Brendan Eich <brendan at mozilla.org> wrote:
Dmitry Soshnikov wrote:
Will the "Existential Operator" for properly accessors be something interesting to consider for ES7 spec? Currently CoffeeScript uses it well.
Please see
esdiscuss.org/topic/sept-18-tc39-meeting-notes#content-2
and find "ARB: This is non-compositional". Citing text for reader convenience:
Existential Operator (strawman discussion)
(Presented by Brendan Eich, Mozilla)
Significant desire include a null and undefined check in syntax/operator form (a la coffeescipt)
o = {} r = o?.p.q.r r = o?.p?.q.r
Mixed discussion about the needs and use cases as they apply to coffeescript code.
ARB: This is non-compositional
o = {} r = o?.p.q.r r = (o?.p).q.r r = o?.p.q.r()
Results in…
var o, r; o = {}; r = o != null ? o.p.q.r : void 0; r = (o != null ? o.p : void 0).q.r; r = o != null ? o.p.q.r() : void 0;
Non-starter.
Yeah, that's the semantics CoffeeScript uses.
DH: Why not an operator that needs to be explicit?
o?.p?.q?.r
LH: Why would you ever even use it on the first?
BE: Forget all of the problems with coffeescript's impl, the need exists.
OK.
YK: In the common cases, where it works, it works well. Where it doesn't, it falls apart unexpectedly.
WH: What about other contexts such as p?[x], p?.q[x], and p?(x) ? [Note that grammar problems arise for some of those.]
The grammar can be tweaked seems.
General agreement.
Conclusion/Resolution Seems useful, but not now. Semantics are unclear
Yeah, so now, when ES6 is closed, probably the topic can be reiterated later on for ES7.
The notes ended a bit too optimistically in my view! "Non-starter".
Yeah, for ES6 it's pretty optimistically :)
OK, thanks again for clarifying this Brendan, and for putting the notes here, appreciated.
The only reason I put the topic here, is (not to beat a dead horse of course), is that we recently had a long internal discussion thread about it. I first thought, that we could just implement an internal JS extension for now, and see how it goes (and if it goes well, potentially include it into ES7), but, true, it needs more clarifications and thoughts.
(still doable though)
Dmitry
How about an accumulator? E.g., turn:
a?.b.c.d?.func();
into (if targeting ES5):
var t; (t = a ? a.b : undefined, t = t ? t.c : undefined, t = t ? t.d : undefined, t = t ? t.func() : undefined);
(in a proper VM you'd use the stack, of course, not a temporary variable).
Note how the presence of one ?. operator causes the entire chain (including normal .'s) to be transformed. Not sure what the side effects of this would be, performance-wise.
Joe
then you could go like this ?
function ifPresent(o, nmsp, dflt) {
var r = nmsp.split('.').reduce(ifPresent.$, o);
return r == null ? dflt : r;
}
ifPresent.$ = function (p, c) {
return p ? p[c] : undefined;
};
var a = {
b: {
c: {
d: 123
}
}
};
ifPresent(a, 'b.c.d', 456); // 123
FWIW I think having silent failures all over is not desirable so I'd like to know what's the concrete claimed need for this, if that's possible. (I've only read there's a need but I don't find the rationale)
Take care
Le 21 mai 2014 à 01:30, Andrea Giammarchi <andrea.giammarchi at gmail.com> a écrit :
FWIW I think having silent failures all over is not desirable so I'd like to know what's the concrete claimed need for this, if that's possible. (I've only read there's a need but I don't find the rationale)
The point of the Existential Operator in general, and of the details of its semantics in particular, is not to fail silently (although it can be abused for that), but to have a compact syntax for concrete cases where you must be prepared to receive either null/undefined or an object (as it happens when working with the DOM), and want to yield another value using a definite algorithm (accessing properties, invoking methods). Or do you think to a precise detail of the semantics of the Existential Operator, where silent failures are encouraged?
I don't think silent fails are always a bad thing. I've been trying to make my code robust against unexpected nulls, preferably only in release mode. That's not always easy to do, though (restricting the behavior to release builds), which is why I consciously chose to wait a year until the code was more mature.
Dmitry Soshnikov wrote:
Will the "Existential Operator" for properly accessors be something interesting to consider for ES7 spec? Currently CoffeeScript uses it well.
Please see
esdiscuss.org/topic/sept-18-tc39-meeting-notes#content-2
and find "ARB: This is non-compositional".
David seems to suggest a compositional version: o?.p?.q?.r
I’m assuming that the left-hand side of value?.prop
is an arbitrary value and that the property access is only made if that value is neither undefined
nor null
. AFAICT that’s also how CoffeeScript’s existential operator works.
I’m ambivalent about it, though: it would be useful, but would also add complexity to the language.
Still haven't seen a convincing example but if generally everybody thinks is a must have I'll look quietly aside.
Take care
I've written a lot of coffeescript code and the existential operator is indeed one of the joys of the language. I like David's attempt to bring rigor and compositionality to it. --scott
I never had the need to write CoffeeScript, and if that's the joy, why not just sticking in there? :P
Anyway, I am off this topic ... no problem at all. I will use, and hopefully never abuse, once it lands in JS but as everything is for JS, the hype and the abuse is trivially reached, and this is in my opinion an evil operator.
Best
C. Scott Ananian wrote:
I've written a lot of coffeescript code and the existential operator is indeed one of the joys of the language. I like David's
You mean Claude's?
Le 23 mai 2014 à 03:04, Brendan Eich <brendan at mozilla.org> a écrit :
C. Scott Ananian wrote:
I've written a lot of coffeescript code and the existential operator is indeed one of the joys of the language. I like David's
You mean Claude's?
/be
I must confess to have asked myself the same question at first reading :-p But see the message of Axel posted a few hours ago in this thread.
Many times I wish there was Existential Operator, so here is my comment when we reconsider it in the future...
On 20 May 2014 12:36, Brendan Eich <brendan at mozilla.org> wrote:
WH: What about other contexts such as p?[x], p?.q[x], and p?(x) ? [Note that grammar problems arise for some of those.]
p?[x] and p?(x) are confusing with ?: ternary operator
so instead p?.[x] and p?.(x) may be better to avoid that confusion.
Claude Pache wrote:
Le 23 mai 2014 à 03:04, Brendan Eich<brendan at mozilla.org> a écrit :
C. Scott Ananian wrote:
I've written a lot of coffeescript code and the existential operator is indeed one of the joys of the language. I like David's You mean Claude's?
/be
I must confess to have asked myself the same question at first reading :-p But see the message of Axel posted a few hours ago in this thread.
Where Axel wrote
David seems to suggest a compositional version:
o?.p?.q?.r
I see a different problem: so heavyweight that many people will say it
isn't worth the cost of standardizing, and what about the ?(
form in
CoffeeScript?
I did indeed mean Claude's proposal in esdiscuss.org/topic/specifying-the-existential-operator-using-abrupt-completion-- my fault for assuming that's what Axel was talking about and not taking the time to double-check the author before quoting him! I apologize, Claude.
(I remember, I mentioned this couple of years ago, but not sure about whether it was considered, etc)
Will the "Existential Operator" for properly accessors be something interesting to consider for ES7 spec? Currently CoffeeScript uses it well.
var street = user.address?.street;
The
street
is either the value of theuser.address.street
if theaddress
property exists (or even if it's an object), ornull
/undefined
otherwise.This (roughly) to contrast to:
var street = user.address && user.address.street;
(the chain can be longer in many cases).
The same goes with methods:
var score = user.getPlan?().value?.score;
If potentially it could be interesting for ES7, I'll be glad helping with the proposal, grammar and algorithm (unless it was considered previously, and decided that it's not for ES for some reason).
P.S.: I tried to solve this issue using default values of destructuring assignment, but it doesn't help actually.
Dmitry