On Jun 19, 2012, at 12:44 AM, Brendan Eich wrote:

> 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.

I can't tell either.

What I'm concerned about above is the first object reference in a chain of 
existential operators. I was trying to illustrate a possible issue with your 
semantics when  the existence of a property is conditional but the object that 
would have the property is expected to exist.  For example when
   foo?.bar
is intended to only be conditional on the existence of property "bar" and not 
on the existence of an object value of foo.  It's all a matter of user intent. 
Are they thinking "access bar if it exists in foo" or are they thinking "access 
foo.bar if it exists".

Errors such as the missing initializer in my example will be obscured when 
users are thinking the first way.

This is probably an area where feedback from CoffeeScript usage would be 
informative. We've heard thatCoffeeScript developer have found ?. to have high 
utility. I haven't heard anything  about  possible negative experiences, for 
example ones such as I'm talking about above. Is this because, in practice, it 
isn't a problem.  Or perhaps nobody has spoken up.  So I'm asking. CoffeeScript 
users: has use of ?. created any problems for you?

> 
> 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".

More below, but an issue may be ?. without .() and that combination has not yet 
been tested 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.

No doubt, but as I'm been trying to express it may also present a hazard.  I'm 
just trying to understand the nature and severity of the hazard and to explore 
whether there are possible mitigations. 

> 
>> 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.

And I'm not suggesting such a syntactic solution. I am suggesting that there is 
a forward value propagation semantics that would have the desired behavior. 

> 
>> 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).

You've already deviated from CoffeeScript by not having ?().  Some of the cow 
paths are now a dead-end, so you need to look at where the cows were going 
rather than how they got there.

When would anybody every write:
   foo?.bar()
and want the call to throw?  If that was what they wanted why not say:  
foo.bar()
My proposal may be different from CoffeeScript, but it would seem to exactly 
reflect what a programmer is likely to want and my semantic sketch showed how 
it would work. I don't see anything confusing in my suggest semantics, I see 
the exact opposite. 

> 
> 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:

Yes, what I'm suggesting doesn't deal with the "only invoke if a function" use 
case. However, I'm guessing that the "only try to invoke if it exists" use case 
is far more common.  I'm suggesting that my semantics addresses the sweet spot 
of CoffeeScript combined ?. and ?() usage without having ?()

> 
> $ 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.

Right, I think that f?() is a much less interesting use case than foo?.bar?()

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

I still stand by my alternative semantics as being a way to address the more 
important use case without have ?()

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

That would be good.

The other question would be how often do you see
   foo?.bar()
used intentionally rather than
  foo?.bar?()
Ever?

Allen
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to