Do All? and Any? Guarantee Short-Circuit Evaluation

Do all? and any? guarantee short-circuit evaluation?

Yes.

In the final draft of the Ruby standard, all? is defined as such:

  1. Invoke the method each on the receiver
  2. For each element X which the method each yeilds:
    1. If block is given, call block with X as argument. If this call returns a falseish object, return false.
    2. If block is not given, and X is a falseish object, return false.
  3. Return true.

Note the word return in step 2. This guarantees short circuit evaluation. any? is defined similarly. However the standard is still a draft and I don't know which Ruby implementations (if any) aim to be standards-compliant.

Is Short Circuit Evaluation guaranteed In C++ as it is in Java?

Yes, it is guaranteed for the "built in" types. However, if you overload && or || for your own types, short-circuited evaluation is NOT performed. For this reason, overloading these operators is considered to be a bad thing.

Do all() and any() always short-circuit in order?

According to the python documentation :

all(iterable)

Return True if all elements of the iterable are true (or if the iterable is empty). Equivalent to:

def all(iterable):
for element in iterable:
if not element:
return False
return True

So as said in the comments the answer is yes, if the order of your iterable is stable.

Does Python's `all` function use short circuit evaluation?

Yes, it short-circuits:

>>> def test():
... yield True
... print('one')
... yield False
... print('two')
... yield True
... print('three')
...
>>> all(test())
one
False

From the docs:

Return True if all elements of the iterable are true (or if the iterable is empty). Equivalent to:

def all(iterable):
for element in iterable:
if not element:
return False
return True

So when it returns False, then the function immediately breaks.

Does Python's `all` function use short circuit evaluation?

Yes, it short-circuits:

>>> def test():
... yield True
... print('one')
... yield False
... print('two')
... yield True
... print('three')
...
>>> all(test())
one
False

From the docs:

Return True if all elements of the iterable are true (or if the iterable is empty). Equivalent to:

def all(iterable):
for element in iterable:
if not element:
return False
return True

So when it returns False, then the function immediately breaks.

Is it guaranteed that bitwise and for bool does not short circuit?

Unless explicitly specified by the standard, all operands of an operator are evaluated and unsequenced1 in C++:

[intro.execution]

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.
[...]
The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. [...]

The only three exceptions that come to my mind are the &&, || and ?: operators2.

The standard even mentions for &&3 that:

[expr.log.and]

Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.

As for if this is good programming style, this is opinion-based.


1 Unsequenced basically means that if you have A @ B (where @ is an operator), B (and its side effects) can be evaluated before A, which is why construct such as i++ + ++i are undefined behavior.

2 Note that for overloaded && and || operator, this is not true anymore since both operands are evaluated. ?: cannot be overloaded.

3 There is a similar note for | within [expr.log.or].

How does C++ handle &&? (Short-circuit evaluation)

Yes, the && operator in C++ uses short-circuit evaluation so that if bool1 evaluates to false it doesn't bother evaluating bool2.

"Short-circuit evaluation" is the fancy term that you want to Google and look for in indexes.

The same happens with the || operator, if bool1 evaluates to true then the whole expression will evaluate to true, without evaluating bool2.

In case you want to evaluate all expressions anyway you can use the & and | operators.

Is short-circuiting logical operators mandated? And evaluation order?

Yes, short-circuiting and evaluation order are required for operators || and && in both C and C++ standards.

C++ standard says (there should be an equivalent clause in the C standard):

1.9.18

In the evaluation of the following expressions

a && b
a || b
a ? b : c
a , b

using the built-in meaning of the operators in these expressions, there is a sequence point after the evaluation of the first expression (12).

In C++ there is an extra trap: short-circuiting does NOT apply to types that overload operators || and &&.

Footnote 12: The operators indicated in this paragraph are the built-in operators, as described in clause 5. When one of these operators is overloaded (clause 13) in a valid context, thus designating a user-defined operator function, the expression designates a function invocation, and the operands form an argument list, without an implied sequence point between them.

It is usually not recommended to overload these operators in C++ unless you have a very specific requirement. You can do it, but it may break expected behaviour in other people's code, especially if these operators are used indirectly via instantiating templates with the type overloading these operators.

Safety concerns about short circuit evaluation

The evaluation order of short-circuit operators (|| and &&) is guaranteed by the standard to be left to right (otherwise they would lose part of their usefulness).

§6.5.13 ¶4

Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation;
there is a sequence point after the evaluation of the first operand. If the first operand
compares equal to 0, the second operand is not evaluated.

§6.5.14 ¶4

Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; there is
a sequence point after the evaluation of the first operand. If the first operand compares
unequal to 0, the second operand is not evaluated.



Related Topics



Leave a reply



Submit