Operators ||= and &&=

# Garrett Smith (15 years ago)

In previous discussion of ES4 (now obsolete), someone (Brendan?) mentioned ||= and &&= short-circuit operators. I was interested, but have heard nothing further on the topic.

Was the idea abandoned?

Garrett

# Brendan Eich (15 years ago)

On May 4, 2009, at 9:35 PM, Garrett Smith wrote:

In previous discussion of ES4 (now obsolete), someone (Brendan?) mentioned ||= and &&= short-circuit operators. I was interested, but have heard nothing further on the topic.

Was the idea abandoned?

Not at all, but some discussion involving ??= instead kind of trailed
off. See

mail.mozilla.org/pipermail/es5-discuss/2008-August thread.html#502

I think ||= makes sense given the extant JS idiom: var foo = arg ||
defaultFoo; that is widely used.

&&= doesn't have a real-world use-case.

??= and ?? are too narrowly typed for JS.

# Mark S. Miller (15 years ago)

On Mon, May 4, 2009 at 10:26 PM, Brendan Eich <brendan at mozilla.com> wrote:

mail.mozilla.org/pipermail/es5-discuss/2008-August/thread.html#502

There is no 502 anchor on that page.

# Brendan Eich (15 years ago)

Sorry, not sure what went wrong. Try this:

mail.mozilla.org/pipermail/es5-discuss/2008-August thread.html#1704

# Peter Michaux (15 years ago)

On Mon, May 4, 2009 at 10:26 PM, Brendan Eich <brendan at mozilla.com> wrote:

??= and ?? are too narrowly typed for JS.

I had the impression from the previous thread that you were more in favor of ??= than ||=. People often write the following at the beginning of functions for optional parameters

optionalParam = optionalParam || defaultVal;

I believe what they are really trying to write is

optionalParam = optionalParam === undefined ? defaultValue : optionalParam;

which is what ??= would do.

I think optional parameters are the nuisance use case that is fueling any discussion about a ||= or ??= operator. I think other use cases are less common and probably would not warrant adding a new operator. The reason I mention this is if there is another sugar plan for default parameter values then perhaps ||= and ??= aren't needed at all (though I think they are probably worth adding.)

I thought default parameters were going to be something like the following.

function(a=1, b="defaultVal");

And in this syntax will default values be used if the parameter is falsey or only if it is undefined?

Peter

# Mark S. Miller (15 years ago)

On Tue, May 5, 2009 at 11:37 AM, Peter Michaux <petermichaux at gmail.com> wrote:

function(a=1, b="defaultVal");

And in this syntax will default values be used if the parameter is falsey or only if it is undefined?

Or only if it is absent?

# liorean (15 years ago)

On Tue, May 5, 2009 at 11:37 AM, Peter Michaux <petermichaux at gmail.com> wrote:

function(a=1, b="defaultVal");

And in this syntax will default values be used if the parameter is falsey or only if it is undefined?

2009/5/5 Mark S. Miller <erights at google.com>:

Or only if it is absent?

I've been out of the ECMAScript world for many months now, but IIRC in ES3 all formal parameters that are absent gets initiated to the value undefined. Not sure which side of the function call border that initiation takes place on, though. Wouldn't special casing absence from undefined value effectively introduce another state for a variable to be in, though, since the behaviour is indistinguishable in user code in ES3?

# Brendan Eich (15 years ago)

On May 5, 2009, at 12:16 PM, liorean wrote:

On Tue, May 5, 2009 at 11:37 AM, Peter Michaux <petermichaux at gmail.com

wrote: function(a=1, b="defaultVal");

And in this syntax will default values be used if the parameter is falsey or only if it is undefined?

2009/5/5 Mark S. Miller <erights at google.com>:

Or only if it is absent?

That's how harmony:default_parameter_values specifies it. Only if absent is an actual argument count vs. formal
parameter count check.

I've been out of the ECMAScript world for many months now, but IIRC in ES3 all formal parameters that are absent gets initiated to the value undefined. Not sure which side of the function call border that initiation takes place on, though.

See harmony:default_parameter_values -- callee side.

Wouldn't special casing absence from undefined value effectively introduce another state for a variable to be in, though, since the behaviour is indistinguishable in user code in ES3?

No, no added state is required beyond the existing actual vs. formal
parameter counts.

# Brendan Eich (15 years ago)

On May 5, 2009, at 11:37 AM, Peter Michaux wrote:

On Mon, May 4, 2009 at 10:26 PM, Brendan Eich <brendan at mozilla.com>
wrote:

??= and ?? are too narrowly typed for JS.

I had the impression from the previous thread that you were more in favor of ??= than ||=.

Only with an important condition. In reply to Ingvar (his words are >>

cited), I wrote:

Suppose you add both ||= and ??=. I think very soon a rule of good practices will spread, recommending to always use ??= for defaults, never ||=, because ||= can trip you up with its zero/false/empty-string irregularity, and ??= is always right.

Then according to the principle I argue above, no intentional deadwood, we should add only ??= and ??. Ruby users will cope, and we avoid the slight difference between ||= in Ruby and ||= in ES4.

But I am not convinced using ??= is beter than ||=. This was pulled from the thread I cited (with corrected anchor), at mail.mozilla.org/pipermail/es5-discuss/2008-August thread.html#1704 The message the above text came from is at mail.mozilla.org/pipermail/es5-discuss/2008-August/000509.html

People often write the following at the beginning of functions for optional parameters

optionalParam = optionalParam || defaultVal;

I believe what they are really trying to write is

optionalParam = optionalParam === undefined ? defaultValue :
optionalParam;

which is what ??= would do.

You could be right, but the fact is people use ||, which equates falsy
values to not short-circuit the defaultVal evaluation. This is what
the code does, not necessarily what was meant. It might be better to
pave this cowpath and not try to sell the ?? super-highway ;-).

I think optional parameters are the nuisance use case that is fueling any discussion about a ||= or ??= operator.

Nuisance to you, useful to others -- and I should note, required for
self-hosting the builtins and the DOM in ES.

I think other use cases are less common and probably would not warrant adding a new operator. The reason I mention this is if there is another sugar plan for default parameter values then perhaps ||= and ??= aren't needed at all

Good point, I'll add it to harmony:default_parameter_values (which is in harmony: because at several TC39 meetings it was
considered harmonious; this could be revisited, but for now it's in
that wiki namespace, while ||= is not).

(though I think they are probably worth adding.)

Both?

I thought default parameters were going to be something like the
following.

function(a=1, b="defaultVal");

That's a useless expression closure :-P.

And in this syntax will default values be used if the parameter is falsey or only if it is undefined?

Only if the actual parameter is absent.

# David-Sarah Hopwood (15 years ago)

liorean wrote:

On Tue, May 5, 2009 at 11:37 AM, Peter Michaux <petermichaux at gmail.com> wrote:

function(a=1, b="defaultVal");

And in this syntax will default values be used if the parameter is falsey or only if it is undefined?

2009/5/5 Mark S. Miller <erights at google.com>:

Or only if it is absent?

I've been out of the ECMAScript world for many months now, but IIRC in ES3 all formal parameters that are absent gets initiated to the value undefined. Not sure which side of the function call border that initiation takes place on, though. Wouldn't special casing absence from undefined value effectively introduce another state for a variable to be in, though, since the behaviour is indistinguishable in user code in ES3?

It's not indistinguishable; exactly the first arguments.length parameters are present, regardless of whether they are undefined.

# Peter Michaux (15 years ago)

On Tue, May 5, 2009 at 2:59 PM, Brendan Eich <brendan at mozilla.com> wrote:

On May 5, 2009, at 11:37 AM, Peter Michaux wrote:

On Mon, May 4, 2009 at 10:26 PM, Brendan Eich <brendan at mozilla.com> wrote:

People often write the following at the beginning of functions for optional parameters

optionalParam = optionalParam || defaultVal;

I believe what they are really trying to write is

optionalParam = optionalParam === undefined ? defaultValue : optionalParam;

which is what ??= would do.

You could be right, but the fact is people use ||, which equates falsy values to not short-circuit the defaultVal evaluation. This is what the code does, not necessarily what was meant. It might be better to pave this cowpath and not try to sell the ?? super-highway ;-).

A lot of people don't understand JavaScript falsey value equality and since || works in their server-side language they assume it works the same way in JavaScript. It compiles and runs after all! ;-)

A small marketing campaign to encourage the ?: version above might change what people use.

I think optional parameters are the nuisance use case that is fueling any discussion about a ||= or ??= operator.

Nuisance to you, useful to others

I think I was unclear. Optional parameters are definitely useful. It is the following idiom's verbosity that is the nuisance (to be possibly alleviated by a new operator.)

optionalParam = optionalParam || defaultValue;

(though I think they are probably worth adding.)

Both?

I don't think ||= and ??= are very difficult to define clearly. Perhaps just a line each in terms of the expanded syntax. I don't think they would add much bloat to engines. Perhaps just better to add them both and move on to discussing classes, lambdas, or processes.

And in this syntax will default values be used if the parameter is falsey or only if it is undefined?

Only if the actual parameter is absent.

Well that is more useful than the ||= or ??= idioms at the top of the function body anyway. Someone passing the value "undefined" to a function causes problems for the idioms.

Someone may want to still use the ||= or ??= idioms for testing properties inside an object passed to the function. I do that when the last parameter to a function is a bunch of different named optional parameters. Unfortunately simple idiom tests for properties inside an object could still be fooled if someone sets a property to "undefined".

Peter

# Brendan Eich (15 years ago)

On May 6, 2009, at 11:07 AM, Peter Michaux wrote:

A lot of people don't understand JavaScript falsey value equality and since || works in their server-side language they assume it works the same way in JavaScript. It compiles and runs after all! ;-)

Compiling and running is often all that's ever needed -- so it ain't
"broke."

A small marketing campaign to encourage the ?: version above might change what people use.

I doubt that. No budget, or even: no developer on scene still. For new
code, maybe, but you will hear from many devs who do not want to be
pedantic and use === and ?:. They will argue they know what they're
doing, the code works even for falsy values which are never passed and
covered by tests, and so on. Again, it ain't broke.

I think I was unclear. Optional parameters are definitely useful. It is the following idiom's verbosity that is the nuisance (to be possibly alleviated by a new operator.)

optionalParam = optionalParam || defaultValue;

Gotcha -- still it beats an if statement. The operator precedent from
Ruby (Ruby's ||= is a bit different as discussed in the past) looms
over this thread, though, so let's try to deal with it:

I don't think ||= and ??= are very difficult to define clearly. Perhaps just a line each in terms of the expanded syntax. I don't think they would add much bloat to engines. Perhaps just better to add them both and move on to discussing classes, lambdas, or processes.

I think it's better to leave both out, or add only one, than to add
both. Otherwise too much is added, and we can't easily take anything
out.

In this I think TC39 is agreed, and I'm shoulder to shoulder with Doug
and Mark on this point. I may differ on wanting to add things they
don't see the need for, but I do not want to add "both" or
"everything" just to cater to divergent opinions about how to provide
something like default parameter values.

Current position: long default parameter values, short ||= and ??=.

Only if the actual parameter is absent.

Well that is more useful than the ||= or ??= idioms at the top of the function body anyway. Someone passing the value "undefined" to a function causes problems for the idioms.

Indeed!

# Mark S. Miller (15 years ago)

On Wed, May 6, 2009 at 12:42 PM, Brendan Eich <brendan at mozilla.com> wrote:

Current position: long default parameter values, short ||= and ??=.

I like that. The great virtue of ||= is that it can be explained as repairing a non-orthogonality, thereby making the language simpler to explain. But ||= is accident prone due to the falsy issue. &&= is not as accident prone, but makes the explanation of the language more complex.

Default parameter values are intuitive and reliable.

# Edward Lee (15 years ago)

On Tue, May 5, 2009 at 1:37 PM, Peter Michaux <petermichaux at gmail.com> wrote:

I think optional parameters are the nuisance use case that is fueling any discussion about a ||= or ??= operator.

There are other uses that are similar, but wouldn't be covered by default args. Here's one simple example:

let (hash = {}) function get(key) hash[key] ??= 123

Similarly, if APIs use a single object to take optional args instead of using function args:

// args is a hash with optional keys "str" and "val" function foo(args) { args.str ??= "bar"; args.val ??= 10; typeof_check(args, { str: "string", val: "number" }) }

So even if there's a better solution for default args than ||= or ??=, there's still use for the operators.

Ed

# Peter Michaux (15 years ago)

On Wed, May 6, 2009 at 1:24 PM, Edward Lee <edilee at mozilla.com> wrote:

On Tue, May 5, 2009 at 1:37 PM, Peter Michaux <petermichaux at gmail.com> wrote:

I think optional parameters are the nuisance use case that is fueling any discussion about a ||= or ??= operator. There are other uses that are similar, but wouldn't be covered by default args. Here's one simple example:

let (hash = {}) function get(key) hash[key] ??= 123

Similarly, if APIs use a single object to take optional args instead of using function args:

// args is a hash with optional keys "str" and "val" function foo(args) {  args.str ??= "bar";  args.val ??= 10;  typeof_check(args, { str: "string", val: "number" }) }

So even if there's a better solution for default args than ||= or ??=, there's still use for the operators.

I was trying to mention these cases but the examples make it more clear. I think that there are still use cases for ||= and ??= but the default args is the most common use case. If the main use case is taken care of with default args then is it necessary to add ||= and ??= for less common use cases?

Peter

# Ash Berlin (15 years ago)

I don't think ||= and ??= are very difficult to define clearly. Perhaps just a line each in terms of the expanded syntax. I don't think they would add much bloat to engines. Perhaps just better to add them both and move on to discussing classes, lambdas, or processes.

a ||= b; a = a || b;

a ??= b; a = a === undefined ? b : a;

And in this syntax will default values be used if the parameter is falsey or only if it is undefined?

Only if the actual parameter is absent.

Well that is more useful than the ||= or ??= idioms at the top of the function body anyway. Someone passing the value "undefined" to a function causes problems for the idioms.

Someone may want to still use the ||= or ??= idioms for testing properties inside an object passed to the function. I do that when the last parameter to a function is a bunch of different named optional parameters. Unfortunately simple idiom tests for properties inside an object could still be fooled if someone sets a property to "undefined".

If someone calls myFunc({option: undefined}) I assume the meant to
explicitly pass an undefined value. The correct idiom for testing this
would be

var opt = "option" in arg ? arg.option : "default";

But this is a fairly rare usage.

Perl has has ||= for a long time (or-equals: var a = a || a_default)
and Perl 5 v10 added the defined-or-equal '//=' and defined-or '//'
operators. I'm not a huge fan of the sigil chosen for perl mind:

$foo //= "default"; $foo = defined $foo ? $foo : "default";

You could make a case for adding a ?? operator for symmetry. Example
of usage:

some_func(a, b ?? "c" );

P.S. Appolgies to anyone who got a copy of this directly. I sent it to
the list from the wrong address previously.

# Brendan Eich (15 years ago)

On May 6, 2009, at 1:43 PM, Ash Berlin wrote:

I don't think ||= and ??= are very difficult to define clearly. Perhaps just a line each in terms of the expanded syntax. I don't think they would add much bloat to engines. Perhaps just better to
add them both and move on to discussing classes, lambdas, or processes.

a ||= b; a = a || b;

Is the reference to |a| computed only once, and before b is evaluated?
This matters in JS since evaluating b could change where |a| exists on
the scope chain.

a ??= b; a = a === undefined ? b : a;

In no case should |a| be evaluated twice here, but this desugaring
does that.

Nothing's ever as simple as you want :-P.

You could make a case for adding a ?? operator for symmetry. Example
of usage:

some_func(a, b ?? "c" );

Roger that, given ??= it would be strange to leave out ??.

I'm still trying to leave out both ;-).

# Ash Berlin (15 years ago)

On 6 May 2009, at 22:38, Brendan Eich wrote:

On May 6, 2009, at 1:43 PM, Ash Berlin wrote:

I don't think ||= and ??= are very difficult to define clearly. Perhaps just a line each in terms of the expanded syntax. I don't think they would add much bloat to engines. Perhaps just better to
add them both and move on to discussing classes, lambdas, or processes.

a ||= b; a = a || b;

Is the reference to |a| computed only once, and before b is
evaluated? This matters in JS since evaluating b could change where | a| exists on the scope chain.

yes.

a ??= b; a = a === undefined ? b : a;

In no case should |a| be evaluated twice here, but this desugaring
does that.

Nothing's ever as simple as you want :-P.

Good point.

a ??= b; if (a === undefined) a = b;

Or if you prefer macro style

var a = (a_val); if (a === undefined) a = (b);

You could make a case for adding a ?? operator for symmetry.
Example of usage:

some_func(a, b ?? "c" );

Roger that, given ??= it would be strange to leave out ??.

I'm still trying to leave out both ;-).

/be

I'm quite partial to an undefined-or operator :)

# Neil Mix (15 years ago)

On May 6, 2009, at 4:53 PM, Ash Berlin wrote:

You could make a case for adding a ?? operator for symmetry.
Example of usage:

some_func(a, b ?? "c" );

Roger that, given ??= it would be strange to leave out ??.

I'm still trying to leave out both ;-).

/be

I'm quite partial to an undefined-or operator :)

Wouldn't it make more sense to have ||| and &&& operators? We're
really just discussing a different form of boolean logic here, why not
go-the-distance and draw parallels to ===. (I think I'm proving
Brendan's point :P)

# Brendan Eich (15 years ago)

On May 6, 2009, at 3:13 PM, Neil Mix wrote:

On May 6, 2009, at 4:53 PM, Ash Berlin wrote:

You could make a case for adding a ?? operator for symmetry.
Example of usage:

some_func(a, b ?? "c" );

Roger that, given ??= it would be strange to leave out ??.

I'm still trying to leave out both ;-).

/be

I'm quite partial to an undefined-or operator :)

Wouldn't it make more sense to have ||| and &&& operators? We're
really just discussing a different form of boolean logic here, why
not go-the-distance and draw parallels to ===. (I think I'm proving
Brendan's point :P)

Which point? ;-)

I tried like hell in 1996-7 to get == and != to be what became ===
and !==, in JS1.2, at the same time ES1 was being standardized. At
that point Microsoft had less market share than Netscape and therefore
did not want to risk "breaking the web", so we standardized == and !=
as the crap-tastic non-equivalence relations they are, and added ===
and !==.

(Adding better forms and hoping to deprecate their precursors is a
constant theme on the Web; nothing against Microsoft's position here,
from this remove in time.)

With the current topic, IMHO there's nothing wrong with || to "fix".
The boolish (truthy/falsy) tolerance and value-preserving, short- circuiting evaluation model are good things in general. So a different
form for a different operator should be used. And C# is our cousin in
Ecma, ECMA-334, which if it has been maintained, has ?? (if not ??=)
in it by now.

# David-Sarah Hopwood (15 years ago)

Ash Berlin wrote:

I don't think ||= and ??= are very difficult to define clearly. Perhaps just a line each in terms of the expanded syntax. I don't think they would add much bloat to engines. Perhaps just better to add them both and move on to discussing classes, lambdas, or processes.

a ||= b; a = a || b;

Note that in general, 'a op= b' is not equivalent to 'a = a op b', the main issue being that 'a op= b' evaluates 'a' once, and 'a = a op b' evaluates it twice.

It is difficult, perhaps impossible, to give a correct expansion of the compound assignment operators in terms of the corresponding non-assigning operator, because there isn't (AFAIK) any way to preserve an evaluated LeftHandSideExpression, without applying GetValue to it, while the right-hand-side is being evaluated. So these operators have to be treated as primitive.