From: Rick DeNatale Date: 2010-01-08T00:31:34+09:00 Subject: Re: group in the array On Thu, Jan 7, 2010 at 4:50 AM, Robert Klemme wrote: > On 01/07/2010 05:00 AM, Ruby Newbee wrote: >> >> On Thu, Jan 7, 2010 at 11:19 AM, Ruby Newbee wrote: >>> >>> On Wed, Jan 6, 2010 at 11:20 PM, Robert Klemme >>> wrote: >>> >>>> inject >>>> http://ruby-doc.org/core-1.8.7/classes/Enumerable.html#M001147 > >>> I have checked the document for inject, but still can't understand for. >>> Can you help explain it with general words by a little samples? > >> Now I checked some other help documents wigh google, and find Ruby's >> inject is similiar to Python's reduce, which is known by me. > > I don't know Python's reduce but a few things are probably noteworthy about > Ruby's #inject: > > It does matter whether you provide an argument or not: > > irb(main):001:0> (1..5).inject {|*a| p a; nil} > [1, 2] > [nil, 3] > [nil, 4] > [nil, 5] > => nil > irb(main):002:0> (1..5).inject(0) {|*a| p a; nil} > [0, 1] > [nil, 2] > [nil, 3] > [nil, 4] > [nil, 5] > => nil > > This means that when summing up you usually want to provide 0 as argument. >  For other use cases, e.g. concatenating you probably do not want to: > > irb(main):003:0> (1..5).inject(0) {|sum,x| sum + x} > => 15 > irb(main):004:0> [].inject(0) {|sum,x| sum + x} > => 0 > > Whithout you do not get a sum for the empty collection: > > irb(main):005:0> [].inject {|sum,x| sum + x} > => nil Which you may or may not want. I'm not sure I see the logic of why you example alone leads to the recommendation to provide the 0 argument: ruby-1.8.7-p174 > (1..5).inject(0) {|sum,x| p [sum, x]; sum + x} [0, 1] [1, 2] [3, 3] [6, 4] [10, 5] => 15 ruby-1.8.7-p174 > (1..5).inject {|sum,x| p [sum, x]; sum + x} [1, 2] [3, 3] [6, 4] [10, 5] => 15 I've come to use inject or reduce depending on whether or not I'm providing the argument, assuming I'm using a version of Ruby which aliases them. I think that inject without an argument is a bit mysterious, because that argument is what you are injecting. I think that most languages which have a form of reduce don't allow that argument, as far as I know, it came from Smaltalk whose form of reduce came from the inject:initialValue into: aBlock method on collection classes. For an old Smaltalker Ruby's inject was no mystery, but using reduce when not supplying the argument makes more sense to me. -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Twitter: http://twitter.com/RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale