Existential operator

Kyle Simpson getify at gmail.com
Wed Apr 13 12:21:04 PDT 2011


>>> See http://wiki.ecmascript.org/doku.php?id=strawman:default_operator --  
>>> the proposal there is ?? and ??= since single ? is ambiguous after an 
>>> expression due to conditional expressions (?:).
>>
>> The "default operator" doesn't address a significant part of what Dmitry 
>> is asking for -- the . in the ?. usage -- which allows the property 
>> access to be expressed only once and used for both the test and 
>> assignment.
>
> This was a one-line FYI, and on-topic in reply to Dmitry's post since he 
> brought up ?= (spelled ??= in the strawman). Why are you objecting to it?

I apologize, I thought you were citing the ??/??= strawman in reference to 
Dmitry's original first question, about the ?. operator. I didn't realize 
you were instead referring to his second question, about ?=.


> I don't see any ?. use case here, so I'm still not sure what this has to 
> do with Dmitry's post or my reply. The topic in the Subject: line is 
> CoffeeScript's existential operator, not anything that might be spelled 
> with a ?

Yes, I apologize for slightly hijacking the thread. I was really just making 
an aside note that part of what Dmitry was asking for, which the ?. in 
Coffeescript does -- allowing the trailing `: undefined` part to be 
omitted -- is something that I indeed find useful in and of itself, and in 
fact would like to see it on the basic ?: operator, if possible.


> First, making : optional introduces a dangling-else ambiguity:
>
>  x = a ? b ? c : d;
>
> This could be (x = a ? (b ? c : d)) or (x = a ? (b ? c) : d).
>
> True, if-else already has this (traditional in C-based languages) 
> ambiguity, "resolved" by associating : with the inner ? and so requiring 
> the programmer to use braces if the other association is wanted, or in 
> general just to avoid trouble. But why should we add more of the same kind 
> of ambiguity, given the benefit of hindsight?

I'm not sure I see how this is really introducing an additional ambiguity? 
As you rightly assert, this "ambiguity" is already present when you chain a 
series of nested ?: usages together, and you already sometimes have to use 
() to dis-ambiguate, something which is long since familiar to those who 
dare to brave the ?: nested chaining. It seems like it's the same ambiguity, 
not additional. But I suppose that's just a matter of perspective.

For `x = a ? b ? c : d`, It seems pretty reasonable and based on existing 
precedent with ?: operator precedence that it'd be taken as  `x = a ? (b ? c 
: d)  {: undefined}`. If that's what you wanted, then it's not ambiguous, 
and you don't need (). If you want the other way, you simply use () and make 
it so. Not sure why this would be bad additional precedent?

I personally tend to avoid that pattern of coding, as I find the potential 
for mishaps greater than the benefit. But in the times where I do use such a 
pattern, I'm cautious to always use (), even when not strictly necessary, so 
in that respect, there'd be no ambiguity to using ?: with optional :, at 
least in the way I code things. And I don't think adding () to some chains 
where you want to override operator precedence is an undue hardship on 
anyone, as you already (sometimes) have to do that with ?:.


> I think the dangling else problem is enough to nix this,

That's a shame. I hope not. But I suppose I'm not surprised if it turns out 
to be so.


> I'm also not sure b is falsy but not undefined in practice. It seems 
> contrived to want a numeric value sometimes, and undefined others. IOW,
>
>  var a = (b > 5) ? b : undefined;
>
> looks like a bug that will result in "undefined" or NaN values propagating 
> via a, some of the time, into other numeric or number to string 
> expressions. It looks like a mis-coded "min" against 5.

In my code, one example where I often use a pattern of something either 
being undefined or having a real value, is in "options" object 
configurations, like when you pass an options hash to a function. For 
instance, if a property is omitted, or it's present but is `undefined`, then 
it's taken to have not been set at all, and thus is either ignored, or in 
some cases is defaulted to some other value. OTOH, if it's set to an actual 
numeric value, then the numeric value is of course used.

The value `null` is another common value used for the purpose of indicating 
"not set" or "ignore this property". I tend to not like that quite as much, 
since `typeof null == "object"` (which can be confused with other types if 
you're not careful) where as `typeof undefined == "undefined"` 
unambiguously.

There's also been a few cases where I've distinguished between a value being 
"undefined" (aka, "not set") and the value being "null" (aka, set 
deliberately to empty). For instance, if you pass in an option with the 
value as `undefined`, that means "not set" and it's ok to grab and use a 
default value for that option. But if you explicitly pass in an option with 
value `null`, that means "disable or ignore me" and don't use the default 
value. I don't use "false" in this case, as it's easy to mistakingly coerce 
that to a 0 numeric value.


In any case, `null` vs. `undefined` aside, having sugar for this pattern 
would just be nice:

var opts = {
   doX: (someX > 0 && someX < 10) ? someX ,   // leaving off the `: 
undefined` (or `: null` if you prefer)
   doY: (someY > 0 && someY < 1) ? someY   // ditto
};
doSomething(opts);

function doSomething(opts) {
   (typeof opts.doX == "undefined") && opts.doX = 5;
   (typeof opts.doY == "undefined") && opts.doY = 0.3;
   (typeof opts.doZ == "undefined") && opts.doZ = "foobar";

   if (opts.doX != null) { ... }
   if (opts.doY != null) { ... }
   if (opts.doZ != null) { ... }
}


--Kyle 



More information about the es-discuss mailing list