I had a scenario arise today where I needed an iterator with similar
semantics as Enumerable#all?, but non-short-circuiting. We came up with
a fairly elegant solution (imho), so I thought I’d be a good rubyzen
and share 
- First… the standard #all? (short-circuits):
irb> (1…5).all? { |i| puts i; i < 3 }
1
2
3
=> false
- Non-short-circuiting version (injecting truth):
irb> (1…5).inject(true) { |retval, i| puts i; retval &&= (i < 3) }
1
2
3
4
5
=> false
- One more way (though I like #2 better)
irb(main):016:0> (1…5).partition { |i| puts i; i < 3 }.last.empty?
1
2
3
4
5
=> false
-Ken
Hmm, why Enumerable#all? without short circuit? If you get to a point
where
the block doesnt apply, then you might aswell break.
j`ey
http://www.eachmapinject.com
Ken Kunz wrote:
3
=> false
-Ken
How about (1…5).map { |x| x < 3 }.all?
Ken Kunz wrote:
3
=> false
-Ken
Also, with #2, obviously your way works, but the &&= isn’t neccesary, a
&& has the intended effect, since the result of the block is put in the
accumulator. Again, it doesn’t matter at all, I’m mostly just writing
to avoid doing work.
Hi –
On Thu, 28 Sep 2006, Ken Kunz wrote:
3
=> false
- One more way (though I like #2 better)
irb(main):016:0> (1…5).partition { |i| puts i; i < 3 }.last.empty?
1
2
3
4
5
=> false
Cool. I want to play too 
[*1…5].map {|i| puts i; i < 3 }.all?
1
2
3
4
5
=> false
David
Hi –
On Thu, 28 Sep 2006, Joey wrote:
Hmm, why Enumerable#all? without short circuit? If you get to a point where
the block doesnt apply, then you might aswell break.
The idea is that it’s a case where you want the block to be executed,
unconditionally, once for every element in the array, and also want to
know whether at least one iteration returned false.
David
How about (1…5).map { |x| x < 3 }.all?
This approach is nice and concise… but I still prefer “truth
injection” for my actual code scenario. In my real code, the block is
multiple lines, and for clarity I don’t love the idea of tacking a
method call on the end of a multi-line block.
Plus I just like saying “injecting truth” 
… obviously your way works, but the &&= isn’t neccesary …
Thanks for the tip.
-Ken
Hi –
On Thu, 28 Sep 2006, Mike H. wrote:
How about (1…5).map { |x| x < 3 }.all?
Whoops, I didn’t see that before I (re)posted it 
David
Mike H. [email protected] wrote:
Also, with #2, obviously your way works, but the &&= isn’t neccesary,
a && has the intended effect, since the result of the block is put in
the accumulator. Again, it doesn’t matter at all, I’m mostly just
writing to avoid doing work.
In that case order should be reversed to avoid short circuiting
altogether
(in this case it does not matter as the test has no side effects, but if
it
had…)
(1…5).inject(true) { |retval, i| puts i; i < 3 && retval}
1
2
3
4
5
=> false
Kind regards
robert
Robert K. wrote:
effects, but if it had…)
Kind regards
robert
Very good point, neglected to think about that, glossing over the fact
that the puts executing doesn’t mean the relevant expression evaluated.
With the fixed example:
irb(main):001:0> (1…5).inject(true) { |s,i| s &&= (puts i; i < 3) }
1
2
3
=> false
irb(main):002:0> (1…5).inject(true) { |s,i| s && (puts i; i < 3) }
1
2
3
=> false
irb(main):003:0> (1…5).inject(true) { |s,i| (puts i; i < 3) && s }
1
2
3
4
5
=> false
With the &&= vs && thing, I made a salient point about a bug in the
example and I was too dumb to realize it.