A couple of weeks ago I was talking about error handling and one option using. short-circuit logic. It had lines that looked like this:

    success = success && FileGetLine(file, headerLine);
    success = success && headerLine == "Date list";

But why couldn’t they look like this:

    success &&= FileGetLine(file, headerLine);
    success &&= headerLine == "Date list";

While you might understand what that means C++ doesn’t, very few languages do.

Short-circuit logic

The normal logic operators we deal with are and, or and xor (exclusive-or). These are part of introductory computing science courses and then fade into the background. In many languages they are represented as &, | and ^ respectively but the English words maybe be used or available as an alternative.

Short-circuit logic operators are available for and and or but not xor. With the first two we can potentially skipping the evaluation of the second operand, with the later it’s just not possible. Computationally they are:

  • a && b is equivalent to !a ? false : b
  • a || b is equivalent to a ? true : b

They are guaranteed to be logically equivalent, the result of the calculations are going to be the same. However the executed code can have effects beyond the simple logic calculation. We can take advantage of that. The example above can be re-written:

    success = !success ? false : FileGetLine(file, headerLine);
    success = !success ? false : (headerLine == "Date list");

Assuming your happy with your ternary conditional operator. If not:

    if (success) {
        success = FileGetLine(file, headerLine);
    }
    if (success) {
        success = (headerLine == "Date list");
    }

Both show the action of the code more strongly. Either success is already false and will stay that way or it will take the value of the new calculation. However, the conditional operator representation is also more wordy. That means it can be harder to get an overview of because their are more details that could matter. Extra details also leave more room for bugs to creep in. The if-statement representation is probably the clearest but, I think, suffers similar problems with larger blocks of code. Overall I prefer the shortened form.

Compound assignment

Many languages have augmented assignment which perform an operation and an assignment in one go:

  • a = a + b; is equivalent to a += b;

This means less repetition and, perhaps, a clearer sense here that a is accumulating changes. There could be a performance advantage as the compiler doesn’t have to create and then throw away a temporary variable.

Missing operator

If you look through C++ list of augmented assignment operators you’ll find arithmetic operators, logic operators but not short-circuit logic operators. There are &= and |=, the logic assignment operators, but those will always perform an evaluation. There is no &&= or ||=, the short-circuit logic assignment operators. It’s not in C, C++, C# or Objective-C. It’s not in D, Go, Java, Pascal, Perl, PHP, Rust or Swift. It is in JavaScript and Ruby. I’m not going to promise that list is entirely correct. I’m looking at this list on Wikipedia and it misclassified Ruby. These operators are definitely uncommon.

I couldn’t find a good discussion of why these operators aren’t present. From what little is out there it seems that combining these two things is considered to be confusing or conflicted and without clear benefit. I’m not sure I agree. To me the presence of one set of augmented assignment operators suggests the others. Indeed some languages go out of there way to say that they are not available.

The actually behaviour of such an operator:

  • a &&= b; would be equivalent to a = a && b;

Makes sense to me. It won’t operate in exactly the same way as the other augmented assignment operators. The second operand doesn’t necessary get evaluated. However that’s just a peculiarity of short-circuit logic operators. It’s something that you learn and then get use to.

A different story

I’ve been away from day-to-day C# development for a while. Since then they’ve gained a null-coalescing operator. The operator, ??, takes the value of it’s left-hand operand if it isn’t null and, otherwise, the value of it’s right-hand operand. That means:

  • a ?? b is equivalent to (a != null) ? a : b

That looks familiar. Re-writing one of my examples above I can get:

  • a || b is equivalent to (a != false) ? a : b

And while the short-circuit operators are all alone the null coalescing operators gets:

  • a ?? = b; is equivalent to a = (a != null) ? a : b;

Is that fair?

On balance

I’d like to try using short-circuit augmented assignment operators in a language. I can already see a use for them in error handling and it would be interesting to see what else they could do. They’re certainly not essential but they would round out a language. Indeed I could argue that not having them is more complicated as it creates special cases.


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *