Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[].all?{} and [].any?{} Behavior

0 views
Skip to first unread message

John Sikora

unread,
Jul 29, 2010, 5:27:52 PM7/29/10
to
I find the following behavior interesting (so interesting that I
modified it), and I would like to hear others' thoughts on the subject:

[3].all? {|element| element == 3 } # => true
[3].all? {|element| element != 3 } # => false (sanity checks)

[].all? {|element| element == 3 } # => true
[].all? {|element| element != 3 } # => true

[].any? {|element| element == 3 } # => false
[].any? {|element| element != 3 } # => false

Ruby 1.8.6 and 1.9.1 both give these results.

The first interesting thing is that both the == and the != checks give
the same logical result (always true for all?, always false for any?).
After thinking about it a little, I decided that this is the desired
behavior.

I also understand why it happens. For example, in the case of all?, the
documentation says that true will be the result if the block never
returns false or nil. In the case of [], the block never gets called, so
the result is true. I know the block never gets called because the
following does not print anything:

[].all? {|dummy| puts 'print something'}, while

[3].all? {|dummy| puts 'print something'} does.

The second interesting thing is that a result of this behavior is that
for the same check, all? will give a result of true, while any? will
give a result of false. This seems contradictory.

I would prefer that for [], both all? and any? would give a result of
false for any check. So I have over-ridden Array#all?, returning false
if self == []. My main motivation for doing so is in situautions such
as:

obj_array.find_all{|obj| obj.attr_1 == x}.all?{|obj| obj.attr_2 == y}

If the find_all returns [], I want the all? result to be false, not
true.

I assume that others have run across this but some quick searches did
not turn up anything. I am wondering how others deal with this such as
over-riding as I do, checking for [] each time (which does not seem very
Ruby-like), or even leaving the operation as is because for some, it may
be the desired behavior.

Finally, are there any potential detrimental effects that might occur
due to the behavior modification that I made. I am not a Rails user (if
that matters), I mainly use Ruby for scripting and hardware control
applications (and I am interested in learning as much as I can about
Ruby because I like it so much).

js
--
Posted via http://www.ruby-forum.com/.

Joseph E. Savard

unread,
Jul 29, 2010, 5:55:41 PM7/29/10
to
The docs pretty clear...
If the block is not given, Ruby adds an implicit block of{|obj| obj} (that
is all? <Enumerable.html#M003131>  will return true only if none of the
collection members are false or nil.)

Its an assumption is always true unless the block tells it something
different..

Assuimng Happy unless its told not to be happy! :-)

irb(main):019:0> [].all? {|e| puts e; e==3}
=> true
irb(main):020:0> [].all? {|e| puts e; e==2}
=> true
irb(main):021:0> [].all? {|e| puts e; e==1}
=> true
irb(main):022:0> [].all? {|e| puts e; e==100}
=> true
irb(main):023:0>


[].all? Is true..

Its interesting.

irb(main):019:0> [].all? {|e| e==3}
=> true
irb(main):020:0> [].all? {|e| e==2}
=> true
irb(main):021:0> [].all? {|e| e==1}
=> true
irb(main):022:0> [].all? {|e| e==100}
=> true
irb(main):023:0>


[].all? Is true..

Its interesting.

John W Higgins

unread,
Jul 29, 2010, 7:39:57 PM7/29/10
to
[Note: parts of this message were removed to make it a legal post.]

Afternoon,

On Thu, Jul 29, 2010 at 2:27 PM, John Sikora <john....@xtera.com> wrote:

> I assume that others have run across this but some quick searches did
> not turn up anything. I am wondering how others deal with this such as
> over-riding as I do, checking for [] each time (which does not seem very
> Ruby-like), or even leaving the operation as is because for some, it may
> be the desired behavior.
>

I might suggest your better course would be to create a new method rather
than override the existing method. Maybe something like js_any? or js_all?
would be better in that it shows both what it's doing and that it's not the
standard method at the same time. Then you have no issues with any other
code that depends on the standard methodology in terms of the methods. I
appreciate the aesthetics are a little lacking but sometimes that a small
price to pay.

John

John Sikora

unread,
Jul 30, 2010, 1:13:42 AM7/30/10
to
David A. Black wrote:

> As I see it, all? and any? make sense in terms of each other. If
> array.all? is true for a condition, that means that array.any? is false
> for the opposite of the condition:
>
> array.all? {|e| cond(e) } == !(array.any? {|e| !cond(e) })
>
> I think that always holds. If [].all? were false, it would not; it would
> flip from true to false depending on how many elements were in the
> array.
>
> To put it in more human terms, array.all? for a condition means: there
> is no element in this array which violates the condition. I know that it
> feels more natural to say "Every element in this array meets this
> condition" -- but the problem with that is precisely that there's no
> guarantee that an array has elements, so it's more accurate to phrase it
> in the negative way.

I must admit that I would never have thought of the behavior in this
manner. But the way that you explain it, it makes sense. When I first
started using Ruby, which was my first (and so far only) OO language, I
found it surprisingly difficult to make the switch from procedural to OO
programming. I really had to change my way of thinking. And this was
just for OO programming, not to mention the Ruby way of thinking as
illustated here. So I ask questions and thankfully,
usually someone can set me straight.

> It feels to me like you're expecting all? to do too many things. I would
> either just use all? as it stands, or do something else entirely, like:
>
> obj_array.find {|obj| obj.attr_1 == x &&! obj.attr_2 == y }
>
> which I've probably garbled but you get the idea :-)

Yes, I know what you mean and I actually have thought of doing something
similar to your code. But a couple of the things that I really like
about Ruby are 1) the Enumerable module itself, and 2) the ability to
string together methods. Well, that and the fact that Ruby is dynamic.
So I probably am asking all? to do too much in this case, but I love to
string methods containing code blocks together as in the example I gave.
So much power in so little space.


> Overriding core methods always has the potential to cause problems,
> because other code (in the interpreter and/or the standard library
> and/or gems and other third-party libraries) may be depending on the
> documented behavior.
>

Yes, I was afraid someone was going to say this (in fact the next person
to reply said the same thing). I think I knew deep down that this was
the case, and that I should leave all? as is.

Thanks,

John Sikora

unread,
Jul 30, 2010, 1:16:36 AM7/30/10
to
John W Higgins wrote:
> I might suggest your better course would be to create a new method
> rather
> than override the existing method. Maybe something like js_any? or
> js_all?
> would be better in that it shows both what it's doing and that it's not
> the
> standard method at the same time. Then you have no issues with any other
> code that depends on the standard methodology in terms of the methods. I
> appreciate the aesthetics are a little lacking but sometimes that a
> small
> price to pay.

After reading your post and the previous post from David, I agree.

Thanks,

Jarmo Pertman

unread,
Jul 30, 2010, 8:57:24 AM7/30/10
to
Hello!

I'd have to agree with John on this one. It is really bizarre that
[].any? returns false and [].all? returns true. It is just not what to
expect without reading documentation and thinking about every word
written in there and trying things out in irb.

I love Ruby because most of the time everything just works as you'd
expect without reading any documentation at all and this is not the
case. It just doesn't make sense that asking Ruby to answer the
question "does this empty collection have all elements as 3?" to
return true. Read again the question and you'll understand what i
mean. Again, if i think about Ruby being a very much like a version of
an English language, then this doesn't make sense also.

And since i'd expect it to do what i have been expected then i haven't
thought about this situation ever also. I'd consider this to be
changed in future versions of Ruby, but what am i to decide on such
things :)

It would make sense if [].all? and [].any? would return false. Always.

Jarmo Pertman
-----
IT does really matter - http://www.itreallymatters.net

Rick DeNatale

unread,
Jul 30, 2010, 11:49:59 AM7/30/10
to
On Thu, Jul 29, 2010 at 5:27 PM, John Sikora <john....@xtera.com> wrote:
> The second interesting thing is that a result of this behavior is that
> for the same check, all? will give a result of true, while any? will
> give a result of false. This seems contradictory.

Well, there's a theoretical basis for this. Enumeration#all? is an
implementation of the universal quantifier from predicate logic (that
upside down A) symbol.

By convention the universal quantifier evaluates to true for an empty set:
http://en.wikipedia.org/wiki/Universal_quantification#The_empty_set
http://en.wikipedia.org/wiki/Vacuous_truth


>
> I would prefer that for [], both all? and any? would give a result of
> false for any check. So I have over-ridden Array#all?, returning false
> if self == []. My main motivation for doing so is in situautions such
> as:
>
> obj_array.find_all{|obj| obj.attr_1 == x}.all?{|obj| obj.attr_2 == y}
>
> If the find_all returns [], I want the all? result to be false, not
> true.
>
> I assume that others have run across this but some quick searches did
> not turn up anything. I am wondering how others deal with this such as
> over-riding as I do, checking for [] each time (which does not seem very
> Ruby-like), or even leaving the operation as is because for some, it may
> be the desired behavior.
>
> Finally, are there any potential detrimental effects that might occur
> due to the behavior modification that I made. I am not a Rails user (if
> that matters), I mainly use Ruby for scripting and hardware control
> applications (and I am interested in learning as much as I can about
> Ruby because I like it so much).

For your own usage as long as it doesn't mess up some other code you
are using, feel free.

For library code, such as in a gem I think it would be better to think
up some other method name rather than changing the standard, e.g.

module Enumerable
def non_vacuous_all?(&b)
!empty? && all?(&b)
end
end

[3].all? {|element| element == 3 } # => true
[3].all? {|element| element != 3 } # => false

[].all? {|element| element == 3 } # => true


[].all? {|element| element != 3 } # => true

[3].non_vacuous_all? {|element| element == 3 } # => true
[3].non_vacuous_all? {|element| element != 3 } # => false

[].non_vacuous_all? {|element| element == 3 } # => false
[].non_vacuous_all? {|element| element != 3 } # => false

[].any? {|element| element == 3 } # => false
[].any? {|element| element != 3 } # => false

There may be a better name than non_vacuous_all? but I can't think of one.

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Github: http://github.com/rubyredrick
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Xavier Noëlle

unread,
Jul 30, 2010, 12:54:28 PM7/30/10
to
2010/7/30, Jarmo Pertman <jar...@gmail.com>:

> It just doesn't make sense that asking Ruby to answer the
> question "does this empty collection have all elements as 3?" to
> return true. Read again the question and you'll understand what i
> mean. Again, if i think about Ruby being a very much like a version of
> an English language, then this doesn't make sense also.

There's no easy answer to this question, as there is nothing easy
dealing with an empty list. Can you prove that not all elements in []
equal 3 ? You can't, because no element has another value. Thus, this
is true.

At first glance, I would intuitively agree with you, but after a
while, I can't find a mean to prove what may sound obvious to you (but
is not).

--
Xavier NOELLE

Joel VanderWerf

unread,
Jul 30, 2010, 1:18:14 PM7/30/10
to

Here's one way to think of it, in terms of an example:

pattern = /.../
tests = [ Test.new(...), ..., Test.new(...) ]
runnable_tests = tests.select {|test| pattern === test.name}

if runnable_tests.all?{|test|test.pass}
puts "Ok!"
else
puts "Failed!"
end
__END__

How do we want this program to work if no tests match the pattern? Is it
a failure case? IMO, it is not.

I don't want to code a special case for runnable_tests.empty?

This seems very English-like to me, but YMMV of course.

John Sikora

unread,
Jul 30, 2010, 2:22:44 PM7/30/10
to
Rick Denatale wrote:

> By convention the universal quantifier evaluates to true for an empty
> set:
> http://en.wikipedia.org/wiki/Universal_quantification#The_empty_set
> http://en.wikipedia.org/wiki/Vacuous_truth
>>

Well, that seals it for me. My thinking is wrong if it goes against
convention, not only in Ruby, but in universal quantification.

>
> For library code, such as in a gem I think it would be better to think
> up some other method name rather than changing the standard, e.g.
>
> module Enumerable
> def non_vacuous_all?(&b)
> !empty? && all?(&b)
> end
> end
>
> [3].all? {|element| element == 3 } # => true
> [3].all? {|element| element != 3 } # => false
>
> [].all? {|element| element == 3 } # => true
> [].all? {|element| element != 3 } # => true
>
> [3].non_vacuous_all? {|element| element == 3 } # => true
> [3].non_vacuous_all? {|element| element != 3 } # => false
>
> [].non_vacuous_all? {|element| element == 3 } # => false
> [].non_vacuous_all? {|element| element != 3 } # => false
>
> [].any? {|element| element == 3 } # => false
> [].any? {|element| element != 3 } # => false
>
> There may be a better name than non_vacuous_all? but I can't think of
> one.
>

Agreed, I should use a similar technigue for my specific applications.

John Sikora

unread,
Jul 30, 2010, 2:25:36 PM7/30/10
to
Joel VanderWerf wrote:
> pattern = /.../
> tests = [ Test.new(...), ..., Test.new(...) ]
> runnable_tests = tests.select {|test| pattern === test.name}
>
> if runnable_tests.all?{|test|test.pass}
> puts "Ok!"
> else
> puts "Failed!"
> end
> __END__
>
> How do we want this program to work if no tests match the pattern? Is it
> a failure case? IMO, it is not.
>
> I don't want to code a special case for runnable_tests.empty?
>
> This seems very English-like to me, but YMMV of course.

Yes, I can see where you would want your result to be according to
convention and opposite of what I stated.

Josh Cheek

unread,
Jul 30, 2010, 2:55:03 PM7/30/10
to
[Note: parts of this message were removed to make it a legal post.]

On Fri, Jul 30, 2010 at 10:49 AM, Rick DeNatale <rick.d...@gmail.com>wrote:

> module Enumerable
> def non_vacuous_all?(&b)
> !empty? && all?(&b)
> end
> end
>
> [3].all? {|element| element == 3 } # => true
> [3].all? {|element| element != 3 } # => false
>
> [].all? {|element| element == 3 } # => true
> [].all? {|element| element != 3 } # => true
>
> [3].non_vacuous_all? {|element| element == 3 } # => true
> [3].non_vacuous_all? {|element| element != 3 } # => false
>
> [].non_vacuous_all? {|element| element == 3 } # => false
> [].non_vacuous_all? {|element| element != 3 } # => false
>
> [].any? {|element| element == 3 } # => false
> [].any? {|element| element != 3 } # => false
>
> There may be a better name than non_vacuous_all? but I can't think of one.
>
>

How about #appall? to imply that it is a pessimistic implementation of #all?
:)

Robert Klemme

unread,
Jul 31, 2010, 6:07:33 AM7/31/10
to
2010/7/30 Rick DeNatale <rick.d...@gmail.com>:

> On Thu, Jul 29, 2010 at 5:27 PM, John Sikora <john....@xtera.com> wrote:
>> The second interesting thing is that a result of this behavior is that
>> for the same check, all? will give a result of true, while any? will
>> give a result of false. This seems contradictory.
>
> Well, there's a theoretical basis for this.  Enumeration#all? is an
> implementation of the universal quantifier from predicate logic (that
> upside down A) symbol.
>
> By convention the universal quantifier evaluates to true for an empty set:
> http://en.wikipedia.org/wiki/Universal_quantification#The_empty_set
> http://en.wikipedia.org/wiki/Vacuous_truth

To complement this, De Morgan's Laws help do the conversion between
all? and and? variants properly:
http://en.wikipedia.org/wiki/De_Morgan%27s_laws

>> I would prefer that for [], both all? and any? would give a result of
>> false for any check. So I have over-ridden Array#all?, returning false
>> if self == []. My main motivation for doing so is in situautions such
>> as:
>>
>> obj_array.find_all{|obj| obj.attr_1 == x}.all?{|obj| obj.attr_2 == y}
>>
>> If the find_all returns [], I want the all? result to be false, not
>> true.
>>
>> I assume that others have run across this but some quick searches did
>> not turn up anything. I am wondering how others deal with this such as
>> over-riding as I do, checking for [] each time (which does not seem very
>> Ruby-like), or even leaving the operation as is because for some, it may
>> be the desired behavior.
>>
>> Finally, are there any potential detrimental effects that might occur
>> due to the behavior modification that I made. I am not a Rails user (if
>> that matters), I mainly use Ruby for scripting and hardware control
>> applications (and I am interested in learning as much as I can about
>> Ruby because I like it so much).
>
> For your own usage as long as it doesn't mess up some other code you
> are using, feel free.

I disagree: IMHO it is a bad idea to change such fundamental behavior
if only for own code. This opens the door widely for all sorts of
bugs and issues. For example, you get used to #all? doing also the
emptyness check and get confused when reading other code which of
course relies on the regular behavior. Or you forget the "require"
for the file that changes semantics of #all? and #any? and receive in
turn subtly bugs which might be hard to track down. Even worse, you
use library code that in turn uses #all? or #any? without you knowing
it and this code suddenly breaks.

> For library code, such as in a gem I think it would be better to think
> up some other method name rather than changing the standard, e.g.

That's definitively the way to go if the behavior should be put into a method.

Robert Klemme

unread,
Jul 31, 2010, 6:14:27 AM7/31/10
to
2010/7/30 Jarmo Pertman <jar...@gmail.com>:

> I'd have to agree with John on this one. It is really bizarre that
> [].any? returns false and [].all? returns true. It is just not what to
> expect without reading documentation and thinking about every word
> written in there and trying things out in irb.

This behavior is _exactly_ what I expect from these methods.
Otherwise it would break all sorts of boolean logic. These methods
are defined the way they are with good reason - even if this does not
meet your expectation here. It's the most reasonable definition in
light of boolean logic and De Morgan's laws which I believe
*everybody* writing software must know by heart and understand because
it is at the very foundation of our profession.

> I love Ruby because most of the time everything just works as you'd
> expect without reading any documentation at all and this is not the

Frankly, this is a dangerous thing to do. Generally doing away with
documentation will bring you in trouble sooner or later.

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Rick DeNatale

unread,
Jul 31, 2010, 12:22:18 PM7/31/10
to
On Sat, Jul 31, 2010 at 6:07 AM, Robert Klemme
<short...@googlemail.com> wrote:
>
>> For your own usage as long as it doesn't mess up some other code you
>> are using, feel free.
>
> I disagree: IMHO it is a bad idea to change such fundamental behavior
> if only for own code.  This opens the door widely for all sorts of
> bugs and issues.  For example, you get used to #all? doing also the
> emptyness check and get confused when reading other code which of
> course relies on the regular behavior.  Or you forget the "require"
> for the file that changes semantics of #all? and #any? and receive in
> turn subtly bugs which might be hard to track down.  Even worse, you
> use library code that in turn uses #all? or #any? without you knowing
> it and this code suddenly breaks.

Whether or not it's a bad idea, and I tend to agree that it is. I
said what I did for at least two reasons:

1) I tend not to be puritanical, just as I wouldn't restrict what
anyone wanted to do in the privacy of their own homes unless it was
harmful to others, I think you should be able to write whatever code
you want to under the same philosophy, whether or not it's harmful to
you.

2) Since one of the most useful ways to learn anything in such a way
that you remember and internalize it is to make a mistake and realize
the consequences.


>
>> module Enumerable
>>  def non_vacuous_all?(&b)
>>    !empty? && all?(&b)
>>  end
>> end
>>
>> [3].all? {|element| element == 3 }  # => true
>> [3].all? {|element| element != 3 }  # => false
>>
>> [].all? {|element| element == 3 }   # => true
>> [].all? {|element| element != 3 }   # => true
>>
>> [3].non_vacuous_all? {|element| element == 3 }  # => true
>> [3].non_vacuous_all? {|element| element != 3 }  # => false
>>
>> [].non_vacuous_all? {|element| element == 3 }   # => false
>> [].non_vacuous_all? {|element| element != 3 }   # => false
>>
>> [].any? {|element| element == 3 }   # => false
>> [].any? {|element| element != 3 }   # => false
>>

>> There may be a better name than non_vacuous_all? but I can't think of one.
>
> I'd rather stick with two method calls because it makes crystall clear
> what's happening.  Also, you may first want to check for emptyness and
> if else branch based on that knowledge (or the other way round).  In
> other words: often you may want to separate both checks

Here I completely disagree. Extracting commonly used code to a well
named method is an essential part of writing and maintaining code.

for example, I see nothing wrong with the sum method which active
support adds to Enumerable

# Calculates a sum from the elements. Examples:
#
# payments.sum { |p| p.price * p.tax_rate }
# payments.sum(&:price)
#
# The latter is a shortcut for:
#
# payments.inject { |sum, p| sum + p.price }
#
# It can also calculate the sum without the use of a block.
#
# [5, 15, 10].sum # => 30
# ["foo", "bar"].sum # => "foobar"
# [[1, 2], [3, 1, 5]].sum => [1, 2, 3, 1, 5]
#
# The default sum of an empty list is zero. You can override this default:
#
# [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
#
def sum(identity = 0, &block)
if block_given?
map(&block).sum(identity)
else
inject { |sum, element| sum + element } || identity
end
end

Following your argument, this is bad because you might want to use
inject and + separately.

But having such methods doesn't prevent you in the least from using
inject, +, empty?, any? or any other method used to implement a
slightly more abstract extracted method separately. It does help to
keep your code DRY and to make it more understandable overall since
you don't have to re-understand the effect of the separate invocations
each time you encounter them, as long as you are careful and name the
abstraction in an 'intention revealing' way.

And doing this also enables changing the implementation of the
abstraction without holistic changes to the code. Yes I know about de
Morgan's rules (I have a CS degree granted by a 1970's era Electrical
Engineering department). Placing the implementation in an abstraction
allows you to do the math proofs/unit testing and refactoring to meet
particular non-functional requirements in one place, which is a good
thing.

I recently was working on a refactoring a large Rails application
taken over from another development shop, which had several nasty bugs
on just this issue of all? returning true for an empty collection. It
turns out that there are definitely cases where you want to test that
a collection has at least 1 element and that all of the elements have
some property. Having said that perhaps a better name for the method
might be

at_least_one_and_all?

That might be a tad long, but I'd rather have a longer but more
intention revealing name, and let one of the several editors I use
deal with keeping my keystroke count down.

Robert Klemme

unread,
Aug 1, 2010, 8:11:28 AM8/1/10
to
2010/7/31 Rick DeNatale <rick.d...@gmail.com>:

> On Sat, Jul 31, 2010 at 6:07 AM, Robert Klemme
> <short...@googlemail.com> wrote:
>>
>>> For your own usage as long as it doesn't mess up some other code you
>>> are using, feel free.
>>
>> I disagree: IMHO it is a bad idea to change such fundamental behavior
>> if only for own code.  This opens the door widely for all sorts of
>> bugs and issues.  For example, you get used to #all? doing also the
>> emptyness check and get confused when reading other code which of
>> course relies on the regular behavior.  Or you forget the "require"
>> for the file that changes semantics of #all? and #any? and receive in
>> turn subtly bugs which might be hard to track down.  Even worse, you
>> use library code that in turn uses #all? or #any? without you knowing
>> it and this code suddenly breaks.
>
> Whether or not it's a bad idea, and I tend to agree that it is.  I
> said what I did for at least two reasons:
>
> 1) I tend not to be puritanical, just as I wouldn't restrict what
> anyone wanted to do in the privacy of their own homes unless it was
> harmful to others, I think you should be able to write whatever code
> you want to under the same philosophy, whether or not it's harmful to
> you.

I did not want to sound puritanical, just point out that certain
habits are likely to have negative impact over time. And of course I
do agree that everyone should write their code as they see fit.

> 2) Since one of the most useful ways to learn anything in such a way
> that you remember and internalize it is to make a mistake and realize
> the consequences.

LOL

>>> module Enumerable
>>>  def non_vacuous_all?(&b)
>>>    !empty? && all?(&b)
>>>  end
>>> end
>>>
>>> [3].all? {|element| element == 3 }  # => true
>>> [3].all? {|element| element != 3 }  # => false
>>>
>>> [].all? {|element| element == 3 }   # => true
>>> [].all? {|element| element != 3 }   # => true
>>>
>>> [3].non_vacuous_all? {|element| element == 3 }  # => true
>>> [3].non_vacuous_all? {|element| element != 3 }  # => false
>>>
>>> [].non_vacuous_all? {|element| element == 3 }   # => false
>>> [].non_vacuous_all? {|element| element != 3 }   # => false
>>>
>>> [].any? {|element| element == 3 }   # => false
>>> [].any? {|element| element != 3 }   # => false
>>>
>>> There may be a better name than non_vacuous_all? but I can't think of one.
>>
>> I'd rather stick with two method calls because it makes crystall clear
>> what's happening.  Also, you may first want to check for emptyness and
>> if else branch based on that knowledge (or the other way round).  In
>> other words: often you may want to separate both checks
>
> Here I completely disagree.  Extracting commonly used code to a well
> named method is an essential part of writing and maintaining code.

While this is true as a general statement, creating too many methods
with trivial behavior can have a detrimental effect on software
readability and maintainability. The reason is that by doing this you
create additioanl artifacts that need to be documented and understand
by a reader. If on the other hand the idiom "!x.empty? && x.all?
{...}" is seen you can directly understand the behavior from three
basic mechanisms (#empty?, && and #all?) without having to resort to
other documentation. Finding a proper name for the combined method
also needs some careful consideration (as you have shown below).

There is at least the point that there is no universal neutral element
and 0 had to be chosen as default here; it's certainly the proper
value for many (most?) cases in practice but one should at least be
aware of this. If your collection contains strings you would need to
use "" as the neutral element (which strangely enough is called
"identity" here which to me sounds like the identity function which is
something different - but I'm nitpicking).

http://en.wikipedia.org/wiki/Neutral_element
http://en.wikipedia.org/wiki/Identity_function

> Following your argument, this is bad because you might want to use
> inject and + separately.

No, that was not my point. My point was that for the *same*
collection you may want to separate the emptyness check and the any /
all check that you combine in a single method. If you combine both in
a single method you cannot evalute results separately (or rather you
cannot use that method if you need the results separately). This is a
common case if you want to provide user responses that are easier to
understand for a human being.

> But having such methods doesn't prevent you in the least from using
> inject, +, empty?, any? or any other method used to implement a
> slightly more abstract extracted method separately.  It does help to
> keep your code DRY and to make it more understandable overall since
> you don't have to re-understand the effect of the separate invocations
> each time you encounter them, as long as you are careful and name the
> abstraction in an 'intention revealing' way.

As I said above, I do not think that creating new methods makes code
more understandable in all cases.

> And doing this also enables changing the implementation of the
> abstraction without holistic changes to the code.  Yes I know about de
> Morgan's rules (I have a CS degree granted by a 1970's era Electrical
> Engineering department).

The hint was intended for the OP. I never assumed you didn't know De
Morgan's rules.

> Placing the implementation in an abstraction
> allows you to do the math proofs/unit testing and refactoring to meet
> particular non-functional requirements in one place, which is a good
> thing.

Right.

> I recently was working on a refactoring a large Rails application
> taken over from another development shop, which had several nasty bugs
> on just this issue of all? returning true for an empty collection.  It
> turns out that there are definitely cases where you want to test that
> a collection has at least 1 element and that all of the elements have
> some property.  Having said that perhaps a better name for the method
> might be
>
>   at_least_one_and_all?
>
> That might be a tad long, but I'd rather have a longer but more
> intention revealing name, and let one of the several editors I use
> deal with keeping my keystroke count down.

I tend to prefer longer and more telling names as well. As you said,
modern environments provide plenty of utilities to deal with the nasty
typing gracefully.

Maurizio De Santis

unread,
Aug 1, 2010, 12:28:21 PM8/1/10
to
Josh Cheek wrote:
> On Fri, Jul 30, 2010 at 10:49 AM, Rick DeNatale
> <rick.d...@gmail.com>wrote:
>
>> [].all? {|element| element != 3 } # => true
>> There may be a better name than non_vacuous_all? but I can't think of one.
>>
>>
> How about #appall? to imply that it is a pessimistic implementation of
> #all?
> :)

I think that the best name for that method would be

def all!?(&block)
!empty? && all?(&block)
end

It's a pity it is not permitted!

so I propose

def strict_all?(&block)
!empty? && all?(&block)
end

Rick DeNatale

unread,
Aug 1, 2010, 12:46:02 PM8/1/10
to
On Sun, Aug 1, 2010 at 12:28 PM, Maurizio De Santis
<desantis...@gmail.com> wrote:
> Josh Cheek wrote:
>> On Fri, Jul 30, 2010 at 10:49 AM, Rick DeNatale
>> <rick.d...@gmail.com>wrote:
>>
>>> [].all? {|element| element != 3 }   # => true
>>> There may be a better name than non_vacuous_all? but I can't think of one.
>>>
>>>
>> How about #appall? to imply that it is a pessimistic implementation of
>> #all?
>> :)
>
> I think that the best name for that method would be
>
> def all!?(&block)
>  !empty? && all?(&block)
> end

No that doesn't make sense to me all not? Not at all!

All not what?

Personally I think this attempts too hard to make the method name
short, at the expense of revealing the intention.


>
> It's a pity it is not permitted!
>
> so I propose
>
> def strict_all?(&block)
>  !empty? && all?(&block)
> end

I don't like this either, it doesn't evoke the right meaning, to me at
least. What are we being strict about? I would tend to read it as
following strictly the conventional meaning of the existential
quantifier, which the existing Enumerable#all? method already does.

Rick DeNatale

unread,
Aug 1, 2010, 12:49:42 PM8/1/10
to
On Sun, Aug 1, 2010 at 12:45 PM, Rick DeNatale <rick.d...@gmail.com> wrote:
>>
>> def all!?(&block)
>>  !empty? && all?(&block)
>> end
>
> No that doesn't make sense to me all not?  Not at all!
>
> All not what?

And right after I hit send, I realized that I'd probably expect
semantics more like:

#def all!?
def all_not?
if block_given?
all? {|element| ! yield element}
else
all? {|element| ! element}
end
end

Hal Fulton

unread,
Aug 1, 2010, 1:24:37 PM8/1/10
to
[Note: parts of this message were removed to make it a legal post.]

On Sun, Aug 1, 2010 at 11:46 AM, Rick DeNatale <rick.d...@gmail.com>wrote:

> On Sun, Aug 1, 2010 at 12:28 PM, Maurizio De Santis
> <desantis...@gmail.com> wrote:
> > Josh Cheek wrote:
> >> On Fri, Jul 30, 2010 at 10:49 AM, Rick DeNatale
> >> <rick.d...@gmail.com>wrote:
> >>
> >>> [].all? {|element| element != 3 } # => true
> >>> There may be a better name than non_vacuous_all? but I can't think of
> one.
> >>>
> >>>
> >> How about #appall? to imply that it is a pessimistic implementation of
> >> #all?
> >> :)
>

Ho

Hal Fulton

unread,
Aug 1, 2010, 1:25:32 PM8/1/10
to
[Note: parts of this message were removed to make it a legal post.]

On Sun, Aug 1, 2010 at 12:24 PM, Hal Fulton <rubyh...@gmail.com> wrote:

> On Sun, Aug 1, 2010 at 11:46 AM, Rick DeNatale <rick.d...@gmail.com>wrote:
>
>> On Sun, Aug 1, 2010 at 12:28 PM, Maurizio De Santis
>> <desantis...@gmail.com> wrote:
>> > Josh Cheek wrote:
>> >> On Fri, Jul 30, 2010 at 10:49 AM, Rick DeNatale
>> >> <rick.d...@gmail.com>wrote:
>> >>
>> >>> [].all? {|element| element != 3 } # => true
>> >>> There may be a better name than non_vacuous_all? but I can't think of
>> one.
>> >>>
>> >>>
>> >> How about #appall? to imply that it is a pessimistic implementation of
>> >> #all?
>> >> :)
>>
>
>

Sorry, hit send by accident.

How about 'every?' for the non-vacuous 'all?'?

If we really need one, that is.

Hal

David A. Black

unread,
Aug 1, 2010, 1:48:59 PM8/1/10
to
Hi --

Or maybe "all?!" :-)


David

--
David A. Black, Senior Developer, Cyrus Innovation Inc.

The Ruby training with Black/Brown/McAnally
Compleat Philadelphia, PA, October 1-2, 2010
Rubyist http://www.compleatrubyist.com

Maurizio De Santis

unread,
Aug 2, 2010, 5:02:26 PM8/2/10
to
what about "all_and_not_empty" ?
or maybe: "all_and_when_I_say_all_I_say_all!" :D

Josh Cheek

unread,
Aug 2, 2010, 5:40:53 PM8/2/10
to
[Note: parts of this message were removed to make it a legal post.]

What about redefining all? to accept an optional param for what to do when
empty? It doesn't change default behaviour, but lets you get your preferred
behaviour out of it. (note this only works on 1.9, because of how procs take
params in 1.8)


module Enumerable
old_all = instance_method(:all?)
define_method :all? do |emptyval=true,&block|
return emptyval if empty?
old_all.bind(self).call &block
end
end

require 'test/unit'

class NewAllTest < Test::Unit::TestCase
def test_empty
assert ![].all?(false)
assert [].all?(true)
assert [].all?
end
def test_non_empty_no_block
assert ![ nil, true, 99 ].all?(true)
assert ![ nil, true, 99 ].all?(false)
assert ![ nil, true, 99 ].all?
assert [ '', true, 99 ].all?(true)
assert [ '', true, 99 ].all?(false)
assert [ '', true, 99 ].all?
end
def test_non_empty_block
assert [ 1, 3, 99 ].all?( true , &:odd? )
assert [ 1, 3, 99 ].all?( false , &:odd? )
assert [ 1, 3, 99 ].all?( &:odd? )
assert ![ 1, 2, 99 ].all?( true , &:odd? )
assert ![ 1, 2, 99 ].all?( false , &:odd? )
assert ![ 1, 2, 99 ].all?( &:odd? )
end
def test_non_array
assert Hash[*1..10].all? { |key,value| key.odd? && value.even? }
end
end

David A. Black

unread,
Aug 2, 2010, 6:12:50 PM8/2/10
to
Hi --

On Tue, 3 Aug 2010, Josh Cheek wrote:

> What about redefining all? to accept an optional param for what to do when
> empty? It doesn't change default behaviour, but lets you get your preferred
> behaviour out of it. (note this only works on 1.9, because of how procs take
> params in 1.8)
>
>
> module Enumerable
> old_all = instance_method(:all?)
> define_method :all? do |emptyval=true,&block|
> return emptyval if empty?
> old_all.bind(self).call &block
> end
> end

You're working a bit too hard there; you can just do:

module Enumerable
alias old_all all?
def all?(emptyval=true, &block)
return emptyval if empty?
old_all(&block)
end
end

with no need for the round trip to the method object and back.

But I think overall it might be even easier just to call empty? :-) I'm
also not a fan of Boolean arguments. I never remember what they mean.

Josh Cheek

unread,
Aug 3, 2010, 2:36:47 AM8/3/10
to
[Note: parts of this message were removed to make it a legal post.]

I did it that way based on the observations at this blog
http://blog.jayfields.com/2006/12/ruby-alias-method-alternative.html but I
guess if you're working by yourself, you will know you did it and not have
collision issues, and if you're working with a team, you would probably not
be redefining Enumerable#all? so alias is probably a much better choice.

David A. Black

unread,
Aug 3, 2010, 5:52:20 PM8/3/10
to
Hi --

> I did it that way based on the observations at this blog
> http://blog.jayfields.com/2006/12/ruby-alias-method-alternative.html but I
> guess if you're working by yourself, you will know you did it and not have
> collision issues, and if you're working with a team, you would probably not
> be redefining Enumerable#all? so alias is probably a much better choice.

The blog post makes the motivation clearer to me -- thanks. The
Enumerable#all example is (I hope :-) just hypothetical; I definitely
wouldn't advocate overriding it at all.

0 new messages