Existential operator (was: ||= is much needed?)

Brendan Eich brendan at mozilla.org
Tue Jun 19 00:44:49 PDT 2012


Allen Wirfs-Brock wrote:
> "This proposal augments the default operator 
> <http://wiki.ecmascript.org/doku.php?id=strawman:default_operator> by 
> adding syntax to avoid accessing a missing property, specifically |?.| 
> for getting and setting a property from a reference base that might be 
> |undefined| or |null|:" [1]
>
> The specified semantics of proposal actually does more than "avoid 
> accessing a missing property".  It also avoids accessing a property of 
> a /missing object.  For example,/
> /
> /
> function f() {
>    var foo;                   //oops, I forgot to write the 
> initializer expression
>    return foo?.bar;    //returns undefined because foo evaluates to 
> undefined.  foo.bar  would throw
> }
>
> This seems slightly and possibly significantly different from a 
> situation like:
>
> function f(foo={ }) {
>    return foo?.bar;    //returns value of foo.bar or undefined if 
> property bar does not exist, just like foo.bar
> }

I can't tell if you love it or hate it :-P.

Seriously, are you objecting to the reference to the default operator? I 
can take that out.

Adopting CoffeeScript's ?. operator is indeed what I'm proposing. Not 
because of CoffeeScript or anything magical or any argument from 
authority. Rather, because it has been user-tested there, in a language 
with JS's runtime semantics (no change to runtime semantics in CS -- 
"it's just syntax"), and found to be "good".

> In particular, it has the affect of possibly propagating the detection 
> of a simple editorial error like a forgotten initializer further from 
> its place of occurrence.

Yes, that's why it's not the default behavior of ".", revised 
incompatibly as Aymeric mooted.

As an opt-in for writing optional objects or maybe-typed chained 
expressions, it has its proper uses.

> At the least, this behavior probably should be clarified in the 
> description

Will do, I revised the semantics but not the leading blurb.

> The inability to use  ?.  meaningfully in a function call context 
> would seem to make this a only half useful feature.  I suspect many 
> people will initially try to write something like
>      foo?.bar()
> with the expectation that the call will be skipped if  bar doesn't exist.

That's where CoffeeScript provides foo.bar?(), but of course we can't 
make that syntax work. I've tried. An ad-hoc backtracking hack is 
elusive. GLR is not going to fly.

> With these changes, the following would evaluate to undefined:
>     var foo ={},  foo2;
>     foo?.bar()
> but
>      foo.bar();
> would throw.

This misplaces the ?. and deviates from CoffeeScript. Writing foo?.bar() 
means "try to get bar from foo but if foo cannot coerce to object, 
short-circuit to result in *undefined*." The ?. replaces . and means get 
or set, depending on whether the IdentifierName after the ?. is the last 
component in an lvalue (followe by an =), or part of an rvalue 
(including an lvalue's base).

The reason CoffeeScript offers ?( as well as ?. is precisely because, 
given a maybe-null-or-undefined foo.bar, you can not only further ?. 
your way to a baz and fail soft with undefined -- you might also want to 
try to invoke foo.bar as a method and fail soft if it is not invocable 
(typeof foo.bar != "function"). This works for an unqualified identifier 
foo, too:

$ cat /tmp/x.coffee
f = null
f?()
$ ./bin/coffee -p /tmp/x.coffee
(function() {
   var f;

   f = null;

   if (typeof f === "function") {
     f();
   }

}).call(this);

The basis case of this induction is an unqualified identifier, not 
something like foo.bar with a dot or question-dot in it. This shows that 
?. is not sufficient to avoid a TypeError attempting to invoke a 
maybe-function. A variant such as ?( is needed after the unqualified 
identifier.

Alas, we can't use CoffeeScript's nice spelling, and I don't see another 
good way to spell it.

However, I believe (survey needed) that the ?( variant is much less used 
than ?. in practice. Cc'ing Jeremy.

/be


More information about the es-discuss mailing list