Testing out some code in both pry
and irb
, I get the following results:
[1] pry(main)> a = [1, 3, 5, 7, 0]
=> [1, 3, 5, 7, 0]
[2] pry(main)> a.any? {|obj| p obj; 3 / obj > 1}
1
=> true
[3] pry(main)> a.all? {|obj| p obj; 3 / obj > 1}
1
3
=> false
In [2]
and [3]
I see that there appears to be short-circuit evaluation that aborts the iteration as soon as possible, but is this guaranteed behaviour? Reading the documentation there is no mention of this behaviour. I realise that I can use inject
instead as that will iterate over everything, but I'm interested in finding out what the official Ruby view is.
Java's && and || operators use short circuit evaluation.
Short-Circuit Evaluation: Short-circuiting is a programming concept in which the compiler skips the execution or evaluation of some sub-expressions in a logical expression. The compiler stops evaluating the further sub-expressions as soon as the value of the expression is determined.
The Boolean AND and OR operators perform short-circuit evaluation, that is, they evaluate the expression on the right of the operator only when it is necessary to determine the overall result of the expression.
The any?
method just realizes the 'or' logic function over the Enumerable
. It could be interpreted as statement:
y = x1 v x2 v x3 v ... v xn
And the all?
method realizes 'and' logic function over the Enumerable
. It also could be interpreted as statement:
y = x1 * x2 * x3 * ... * xn
Since the Array
is an Enumerable
, it also includes those methods. So, for the method any?
the first occurience of true
(exactly neither nil
nor false
) result breaks enumeration with true
result. In example the yielded becomes true on number 4, so the methods breaks the execution the returns true
:
[1,2,3,4,5].any? {| x | puts x ; x > 3 }
# 1
# 2
# 3
# 4
# => true
Also you can apply DeMorgan's rule to the function any?
, and to use all?
method:
![1,2,3,4,5].all? {| x | puts x ; x <= 3 }
# 1
# 2
# 3
# 4
# => true
For the method all?
the first occurience of either false
or nil
result do something similar, i.e. returns false
. In example the yielded becomes false on number 3, so the methods breaks the execution the returns false
:
[1,2,3,4,5].all? {| x | puts x ; x < 3 }
# 1
# 2
# 3
# => false
And with DeMorgan's transformation to use any?
method:
![1,2,3,4,5].any? {| x | puts x ; x >= 3 }
# 1
# 2
# 3
# => false
Yes.
In the final draft of the Ruby standard, all?
is defined as such:
each
on the receivereach
yeilds:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With