Julia Language Short-circuit operators: && and ||


Example

For branching

The short-circuiting conditional operators && and || can be used as lightweight replacements for the following constructs:

  • x && y is equivalent to x ? y : x
  • x || y is equivalent to x ? x : y

One use for short-circuit operators is as a more concise way to test a condition and perform a certain action depending on that condition. For instance, the following code uses the && operator to throw an error if the argument x is negative:

function mysqrt(x)
    x < 0 && throw(DomainError("x is negative"))
    x ^ 0.5
end

The || operator can also be used for error checking, except that it triggers the error unless a condition holds, instead of if the condition holds:

function halve(x::Integer)
    iseven(x) || throw(DomainError("cannot halve an odd number"))
    x ÷ 2
end

Another useful application of this is to supply a default value to an object, only if it is not previously defined:

isdefined(:x) || (x = NEW_VALUE)

Here, this checks if the symbol x is defined (i.e. if there is an value assigned to the object x). If so, then nothing happens. But, if not, then x will be assigned NEW_VALUE. Note that this example will only work at toplevel scope.

In conditions

The operators are also useful because they can be used to test two conditions, the second of which is only evaluated depending on the result of the first condition. From the Julia documentation:

In the expression a && b, the subexpression b is only evaluated if a evaluates to true

In the expression a || b, the subexpression b is only evaluated if a evaluates to false

Thus, while both a & b and a && b will yield true if both a and b are true, their behavior if a is false is different.

For instance, suppose we wish to check if an object is a positive number, where it is possible that it might not even be a number. Consider the differences between these two attempted implementations:

CheckPositive1(x) = (typeof(x)<:Number) & (x > 0) ? true : false
CheckPositive2(x) = (typeof(x)<:Number) && (x > 0) ? true : false

CheckPositive1("a")
CheckPositive2("a")

CheckPositive1() will yield an error if a non-numeric type is supplied to it as an argument. This is because it evaluates both expressions, regardless of the result of the first, and the second expression will yield an error when one tries to evaluate it for a non-numeric type.

CheckPositive2(), however, will yield false (rather than an error) if a non-numeric type is supplied to it, since the second expression is only evaluated if the first is true.

More than one short-circuit operator can be strung together. E.g.:

1 > 0 && 2 > 0 && 3 > 5