logical-assignment operators

# Steve Yegge (17 years ago)

A little bird told me that TG1 may have dropped support for the assignment operators &&=, ||=, ^^= due to lack of popular demand and/or compelling use cases.

If so, I thought I'd lobby to get at least ||= added back in. I don't know of any really good uses for &&= or ^^=, but ||= is being popularized by Ruby and, in particular, Rails, as a nice shorthand for setting a default value. So you say things like this:

foo.bar ||= default_value;

instead of:

foo.bar = foo.bar || default_value;

Given that the lvalue expression can often be quite long, it can add up to a significant compression.

A quick grep on the Rails trunk shows ||= is used 317 times. Rails simulates keyword parameters by passing around hashes of optional arguments. This of course yields functions that have hundreds of possible code paths, and to consolidate them, the entry-point functions all ||= in default values.

Note that they also make use of the expression's return value, e.g.:

web_service(:one) { @service_one ||= TestInvokeService.new }

Or:

(@signal_handlers ||= Hash.new)[signal] = handler

In the latter case, it was a succinct way to lazily initialize an instance var before assigning to it.

I think we're going to see a lot of Ruby code ported to JavaScript when ES4 hits the big platforms. It's just syntactic sugar, but it's such a common use case (and presumably really easy to support) that I'd vote for including it.

# John Cowan (17 years ago)

Steve Yegge scripsit:

Hi folks,

A little bird told me that TG1 may have dropped support for the assignment operators &&=, ||=, ^^= due to lack of popular demand and/or compelling use cases.

If so, I thought I'd lobby to get at least ||= added back in.

I agree, and I think there is a use case for &&= as well. Suppose that x is either an integer or null. Then

x &&= x + 5;

will increment x by 5 unless it is null, in which case it will be left alone. (This will not work in languages where 0 is false, like C and Perl.)

# Brendan Eich (17 years ago)

On Feb 12, 2007, at 12:51 PM, John Cowan wrote:

Steve Yegge scripsit:

Hi folks,

A little bird told me that TG1 may have dropped support for the assignment operators &&=, ||=, ^^= due to lack of popular demand
and/or compelling use cases.

If so, I thought I'd lobby to get at least ||= added back in.

I agree, and I think there is a use case for &&= as well. Suppose that x is either an integer or null. Then

x &&= x + 5;

will increment x by 5 unless it is null, in which case it will be left alone. (This will not work in languages where 0 is false, like C and Perl.)

'' is false in Perl, so this worksforme in Perl:

$ perl my $x; $x &&= $x + 5; print "$x\n";

Is that what you meant?

BTW, I'm in favor of &&= and ||= now that I think for three seconds
about the || use cases I know, which really wanted ||= all along.

One pill that we spat out along with these, perhaps it was the only
poison: ^^ (and ^^= if ^^ is there). Does anyone have a use-case for
value-preserving ^^? We didn't think so when TG1 last considered
these oddments from Waldemar's draft js2/es4 proposals.

# Sho Kuwamoto (17 years ago)

Just to introduce myself... I'm new to this list, but I've provided feedback on the ECMAScript spec to folks like Jeff Dyer within Adobe.

Perhaps this is just a matter of programming style, but x &&= x + 5

seems cryptic to me, and I personally would prefer if (x != null) x += 5;

in my own coding. I realize that different people feel comfortable with different programming idioms, but how common is this use of &&=? Is the &&= operator really pulling its weight? To my eye, it doesn't add a huge amount of benefit, and could probably be left out of the language.

# Russ Cox (17 years ago)

I realize that different people feel comfortable with different programming idioms, but how common is this use of &&=? Is the &&= operator really pulling its weight?

For one possible source of numbers, compare

www.google.com/codesearch?q="||=", www.google.com/codesearch?q="%26%26="

That also shows that &&= is most commonly used for booleans like ok &&= more_work(), although the usage John Cowan pointed out has its own small fraction.

Even though &&= is much less common than ||=, it seems weird to have ||, &&, ||=, and not &&=. Once ||= is in, I think &&= needs to come along.

(It might also seem weird to have && and || but not ^^, but that's easily explained by the fact that && and || are short-cut booleans while ^^ cannot be.)

Russ

# John Cowan (17 years ago)

Brendan Eich scripsit:

(This will not work in languages where 0 is false, like C and Perl.)

'' is false in Perl, so this worksforme in Perl:

$ perl my $x; $x &&= $x + 5; print "$x\n";

Yes, but when $x is 0, it remains 0.

One pill that we spat out along with these, perhaps it was the only
poison: ^^ (and ^^= if ^^ is there). Does anyone have a use-case for
value-preserving ^^? We didn't think so when TG1 last considered
these oddments from Waldemar's draft js2/es4 proposals.

It's good for handling mutually exclusive options. If you must specify either alpha or bravo, then alpha ^^ bravo will be alpha if alpha was specified, bravo if bravo was specified, and "true" if something is wrong.

# Brendan Eich (17 years ago)

On Feb 12, 2007, at 6:00 PM, John Cowan wrote:

Brendan Eich scripsit:

(This will not work in languages where 0 is false, like C and Perl.)

'' is false in Perl, so this worksforme in Perl:

$ perl my $x; $x &&= $x + 5; print "$x\n";

Yes, but when $x is 0, it remains 0.

Right -- but why would ES4 differ here? ES1-3, any old JS in a
browser, would evaluate 'x = 0; x = x && x + 5; x' to result in 0
too. I did not follow why your original post made the null initial
value case (how about undefined?) special compared to 0, false, or ''.

One pill that we spat out along with these, perhaps it was the only poison: ^^ (and ^^= if ^^ is there). Does anyone have a use-case for value-preserving ^^? We didn't think so when TG1 last considered these oddments from Waldemar's draft js2/es4 proposals.

It's good for handling mutually exclusive options. If you must
specify either alpha or bravo, then alpha ^^ bravo will be alpha if alpha was specified, bravo if bravo was specified, and "true" if
something is wrong.

Sure, but ^^ can't short-circuit, it's not in C, and maybe we can do
without it. I've used (alpha == true) ^ ( bravo == true) and lived.

# John Cowan (17 years ago)

Brendan Eich scripsit:

Yes, but when $x is 0, it remains 0.

Right -- but why would ES4 differ here? ES1-3, any old JS in a
browser, would evaluate 'x = 0; x = x && x + 5; x' to result in 0
too. I did not follow why your original post made the null initial
value case (how about undefined?) special compared to 0, false, or ''.

Brain fart on my part (comes of knowing too many languages with imperfect recall of the details). Yes, that's flaky in any language where zero is false, including Javascript.

Sure, but ^^ can't short-circuit, it's not in C, and maybe we can do
without it. I've used (alpha == true) ^ ( bravo == true) and lived.

That works when alpha and bravo are booleans, but not when they are richer values. OTOH, if they are richer values, you probably still want to keep track of which is which rather than just merging them. Concedo.

# Lars T Hansen (17 years ago)

On Feb 13, 2007, at 3:56 AM, John Cowan wrote:

Brendan Eich scripsit:

Yes, but when $x is 0, it remains 0.

Right -- but why would ES4 differ here? ES1-3, any old JS in a browser, would evaluate 'x = 0; x = x && x + 5; x' to result in 0 too. I did not follow why your original post made the null initial value case (how about undefined?) special compared to 0, false, or
''.

Brain fart on my part (comes of knowing too many languages with
imperfect recall of the details). Yes, that's flaky in any language where zero is false, including Javascript.

Sure, but ^^ can't short-circuit, it's not in C, and maybe we can do without it. I've used (alpha == true) ^ ( bravo == true) and lived.

That works when alpha and bravo are booleans, but not when they are richer values.

The use of == implies a rich set of conversions, so this probably works well most of the time. But a proper definition of ^^ would leave less to chance.

# liorean (17 years ago)

On 13/02/07, Lars T Hansen <lth at acm.org> wrote:

On Feb 13, 2007, at 3:56 AM, John Cowan wrote:

Brendan Eich scripsit:

Yes, but when $x is 0, it remains 0. Right -- but why would ES4 differ here? ES1-3, any old JS in a browser, would evaluate 'x = 0; x = x && x + 5; x' to result in 0 too. I did not follow why your original post made the null initial value case (how about undefined?) special compared to 0, false, or ''. Brain fart on my part (comes of knowing too many languages with imperfect recall of the details). Yes, that's flaky in any language where zero is false, including Javascript.

This is really a problem with using || and && as default and guard operators. I've seen plenty code break because of || used as default operator when the empty string or zero are meant to be legal values. They'd serve as much better default and guard operators if they treated the empty string and zero as true. NaN, null, undefined on the other hand still makes sense to treat as falsy values in default and guard operators.

Maybe adding this behaviour as new operators ||| and &&& with |||= and &&&= assignment variants would be an idea?

# Brendan Eich (17 years ago)

On Feb 13, 2007, at 1:07 AM, Lars T Hansen wrote:

Sure, but ^^ can't short-circuit, it's not in C, and maybe we can do without it. I've used (alpha == true) ^ ( bravo == true) and lived.

That works when alpha and bravo are booleans, but not when they are richer values.

The use of == implies a rich set of conversions, so this probably works well most of the time. But a proper definition of ^^ would
leave less to chance.

And can preserve the value of the operand that converts to true.

Still no short-circuiting, and it seems to lack use cases in
everyone's experiences. Since it evaluates both operands, it can be
written as a function, so TG1 in today's conference call decided to
pass on ^^ and ^^=.

But the good news is that we agreed to support &&= and ||= -- which
are in ActionScript 3 already.

# Brendan Eich (17 years ago)

On Feb 13, 2007, at 6:14 AM, liorean wrote:

On 13/02/07, Lars T Hansen <lth at acm.org> wrote:

On Feb 13, 2007, at 3:56 AM, John Cowan wrote:

Brendan Eich scripsit:

Yes, but when $x is 0, it remains 0. Right -- but why would ES4 differ here? ES1-3, any old JS in a browser, would evaluate 'x = 0; x = x && x + 5; x' to result in 0 too. I did not follow why your original post made the null initial value case (how about undefined?) special compared to 0, false, or ''. Brain fart on my part (comes of knowing too many languages with imperfect recall of the details). Yes, that's flaky in any language where zero is false, including Javascript.

This is really a problem with using || and && as default and guard operators. I've seen plenty code break because of || used as default operator when the empty string or zero are meant to be legal values.

Any code in public JS libraries come to mind? I believe you, but
I've never seen such bugs, and || for defaulting is popular in
Mozilla-hosted JS. (Here's where you promptly hit me with an lxr
link to Moz code that abuses || ;-).

They'd serve as much better default and guard operators if they treated the empty string and zero as true. NaN, null, undefined on the other hand still makes sense to treat as falsy values in default and guard operators.

Ship sailed on that one 12 years ago.

Maybe adding this behaviour as new operators ||| and &&& with |||= and &&&= assignment variants would be an idea?

Inspired by === and !==, but please, let's not. The need for === is
more acute in light of the non-equivalence-relation mess that is ==
(useful mess? I have very mixed feelings, but just because its
intransitive I think == is broken in JS -- and I'm to blame for it!
When we were standardizing ES1, Guy Steele was more jaded; he noted
that Common Lisp has something like five kinds of "equality"
operators, so JS had a long way to go ;-)). Here, absent more
evidence of misuse of || in the field, and without a clearer
connotation for |||, I would be against adding any such operators.

# John Cowan (17 years ago)

Brendan Eich scripsit:

When we were standardizing ES1, Guy Steele was more jaded; he noted
that Common Lisp has something like five kinds of "equality"
operators, so JS had a long way to go ;-)).

By my count, Common Lisp has four general-purpose equality operators (eq, eql, equal, and equalp) and four type-specific equality operators (=, char=, string=, and string-equal).

# liorean (17 years ago)

On 13/02/07, Brendan Eich <brendan at mozilla.org> wrote:

On Feb 13, 2007, at 6:14 AM, liorean wrote:

This is really a problem with using || and && as default and guard operators. I've seen plenty code break because of || used as default operator when the empty string or zero are meant to be legal values. Any code in public JS libraries come to mind? I believe you, but I've never seen such bugs, and || for defaulting is popular in Mozilla-hosted JS. (Here's where you promptly hit me with an lxr link to Moz code that abuses || ;-).

No, it's a too obvious bug for it to appear in any public libraries, and those developers are too experienced to not see the problem directly and fix it in the library right away, before making it public.

But I'm a member of several forums and mailing lists, and it's not an uncommon error seen in code from newcomers to JavaScript that are searching for an explanation why their code doesn't work, especially if they don't have a programming background. but came from HTML/CSS and graphic design directions.

Maybe adding this behaviour as new operators ||| and &&& with |||= and &&&= assignment variants would be an idea? Inspired by === and !==, but please, let's not. The need for === is more acute in light of the non-equivalence-relation mess that is == (useful mess? I have very mixed feelings, but just because its intransitive I think == is broken in JS -- and I'm to blame for it! When we were standardizing ES1, Guy Steele was more jaded; he noted that Common Lisp has something like five kinds of "equality" operators, so JS had a long way to go ;-)). Here, absent more evidence of misuse of || in the field, and without a clearer connotation for |||, I would be against adding any such operators.

One could alway argue that the full spectrum of identity/equality/equivalency/similarity/convertability would make a nicer programming environment, but on the other hand it can also add confusion about which operator is the right one to use...

# Brad Fults (17 years ago)

As far as I can tell [1] there have never been logical assignment operators (AND, OR) in ES and I can't access the spec on the wiki [2] anymore, so I don't know if they're in the spec. I don't see anything in the proposals section, so here's a proposal.

Add two operators to ES:

||=
&&=

The purpose should be obvious, as they mirror the pattern of all other shortcut assignment operators and have existed in other languages for a long time.

Example

a ||= 0
is the same as
a = a || 0

Any insight into the issues surrounding this part of the language would be appreciated.

Thanks.

[1] - developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Operators:Assignment_Operators [2] - spec:spec

# Brendan Eich (17 years ago)

On Oct 9, 2007, at 6:33 PM, Brad Fults wrote:

Hi,

As far as I can tell [1] there have never been logical assignment operators (AND, OR) in ES and I can't access the spec on the wiki [2] anymore, so I don't know if they're in the spec. I don't see anything in the proposals section, so here's a proposal.

Try the reference implementation when in doubt:

$ make repl perl bin/repl-with-readline.pl

a = 1

1

b = 0

0

a &&= b

0

a

0

b = "great!"

great!

a ||= b

great!

a

great!

# Brad Fults (17 years ago)

On 10/9/07, Brendan Eich <brendan at mozilla.org> wrote:

Try the reference implementation when in doubt...

Ah, very nice.

Is there a place where this is documented? I assume it's in the spec, but the spec is apparently not public right now.

Thanks.

# Brad Fults (17 years ago)

On 10/10/07, Brad Fults <bfults at gmail.com> wrote:

Is there a place where this is documented? I assume it's in the spec, but the spec is apparently not public right now.

Never mind. I found the thread about the spec being re-written.

Thanks.