From: "David A. Black" Date: 2010-07-30T07:50:46+09:00 Subject: Re: [].all?{} and [].any?{} Behavior ---993115281-2036552902-1280443424=:3095 Content-Type: MULTIPART/MIXED; BOUNDARY="-993115281-2036552902-1280443424=:3095" This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. ---993115281-2036552902-1280443424=:3095 Content-Type: TEXT/PLAIN; charset=utf-8; format=flowed Content-Transfer-Encoding: 8BIT Hi -- On Fri, 30 Jul 2010, John Sikora wrote: > 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. 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 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. 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 :-) > 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). 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. 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 ---993115281-2036552902-1280443424=:3095-- ---993115281-2036552902-1280443424=:3095--