Logical Assignment Operators
Thought I'd switch gears this week and talk about Logical Assignment Operators (||=, &&=), a feature that is proposed for ECMAScript 4th edition, but is already implemented in ActionScript 3.0. To understand the rationale behind the Logical Assignment Operators, you need to understand how the logical operators in ECMAScript and ActionScript work. Most people think of these operators in purely boolean terms. In other words, if you have two boolean variables, conditionA and conditionB, you can use the logical operators to calculate logical results. For example, if one condition is true and the other is false, the logical AND operator returns a value of false because both conditions have to be true in order for logical AND to return true.
true in this case because it takes only one condition to be true for the logical OR operator to return true:
The logical operators are far more interesting than this, however, in that they are not limited to Boolean values. You can use other values as operands to the logical operators. For example, let's say you want to check whether values have been assigned to a pair of string variables. The result is true only if both variables contain string values.
But it gets even more interesting because the logical operators don't necessarily return a Boolean value. What's really going on is that the logical operator returns the value of one operand or the other. For example, the logical AND operator examines the first operand and if that operand is either false or can be converted to false, the operator returns the first operand and never even looks at the second operand. If the first operand turns out to be true, the second operand is returned. We can see this in action if we just change the type annotation of the variable bothStringsSet in the previous example to type String:
This is null because the value of the first operand, str1, converts to false, so the logical AND operator returns the value of str1, which is null
This is also null because even though the value of the first operand now converts to true, this just means that the logical AND operator returns the value of the second operand, str2, which is still null.
The logical AND operator does the same thing here as it did in the previous code snippet--it returns the value of the second operand because str1 converts to true, but we get a different value as a result because the second operand now has the value bar. That's not a very practical example, so let's look at something that makes a little more sense.
Many programmers use the logical OR operator to assign default values. The logical OR operator is the exact opposite of the logical AND operator. In other words, the logical OR operator returns the first operand if it is either true or can be converted to true, and otherwise returns the second operand. What does this have to do with assigning default values? Well, you only want to assign a default value if a variable is undefined, so you could write the following code to assign a default value:
Alternatively, you could use the logical OR operator to serve the same purpose:
If myVar is undefined, the logical OR operator considers that as false, so it returns the value of the second operand, "default". If myVar has a value assigned already, the logical OR operator considers that as true and just re-assigns the value of myVar to myVar. It's a matter of personal taste. Some argue that using the if statement is easier to read. Nevertheless, there are some programs that use the logical operator technique, so at the very least it's handy to know about it.
Finally, we get to the "assignment" part of the logical assignment operators. For those of you who find the logical OR technique for assigning default values distasteful because it's hard to read, you may want to stop reading now. I say this because a common technique among Ruby and Perl programmers is to use an even more abbreviated form of this technique that takes advantage of the logical OR assignment operator. In other words, the following code:
can be rewritten using the logical OR assignment operator:
There you have what I believe to be the most common use of the logical OR assignment operator. Examples of the logical AND assignment operator are less common, but one use-case could be to increment a variable, but only when that variable is greater than zero. For example, the following code increments myNum only if it is not zero:
As parting words, I should say that I'm not advocating the use of this technique, but I do think it's worth understanding because you may come across code that uses this technique.
Comments
Thanks for this. It may not be readable code, but who says you will always be working with readable code. Before I learned the importance of readable code I used to pride myself with writing the most compressed versions of code. I'm sure other people are the same.
I like the simplicity for default writing though. It sure beats:
myVar = myVar == null ? "default" : myVar;
Posted by: Daryl Ducharme | February 7, 2008 1:15 PM
Francis, please keep these posts coming. It's really great to get these bite-sized breakdowns of esoteric and less obvious language features. You're doing a great job.
Posted by: Austin Haas | February 7, 2008 2:43 PM
Austin's comment++
Posted by: Ben Clinkinbeard | February 8, 2008 5:12 PM
I like the idea of using logical operators for validation when a value is allowed to be one of many values like this:
public function validate(newValue:String):Boolean
{
return newValue == SOME_STATIC ||
ANOTHER_STATIC ||
SOME_OTHER_STATIC;
}
Posted by: Jeremy Brown | February 8, 2008 7:36 PM
Ben's comment++
Hopefully not starting a chain of spam, but it's certainly much appreciated!
Posted by: Colin Campbell | February 8, 2008 8:38 PM
Thanks Francis, intersted stuff.
There seems to be some problem viewing the page in Safari OSX. Some of the code that requires to be scrolled doesn't have ScrollBars.
Posted by: Tink | February 9, 2008 5:57 AM
Oops....I caught a mistake in the snippet I posted!! It should look something like this.
public function validate(newValue:String):Boolean
{
return newValue == SOME_STATIC ||
newValue == ANOTHER_STATIC ||
newValue == SOME_OTHER_STATIC;
}
By the way, I've enjoyed reading your posts. Thanks.
Posted by: Jeremy Brown | February 9, 2008 5:58 PM
Hi Tink, I see what you mean about the scroll bar weirdness on Safari OSX. Fortunately, for me at least, I'm able to grab the bottom-right-hand corner and drag it down to enlarge the box. Does that work for you?
Posted by: Francis Cheng | February 11, 2008 10:34 AM
Thanks for that Francis! It's interesting how logical operations are executed, if you had something like this:
If the first expression (nameInput.isNotEmpty) returns false the others are skipped. In order to evaluate all of them I had to do the following:
as for some reason that wouldn't work:
Posted by: Og2t | September 25, 2008 4:03 AM