From: Farrel Lifson Date: 2006-11-15T15:54:48+09:00 Subject: Re: Design problem with 'inject' On 15/11/06, Gary Boone wrote: > > Ruby's inject has a design that can lead to hard to find bugs. The > problem is that you don't have to specify what is summed; the value of > the block is summed. That means 'next' can lead to a bug. Here's an > example: > > No problem: > > arr.inject(0) do |sum, i| > sum += i > done > > But suppose you need to skip some elements, so you add a 'next' > statement. > Problem: > > arr.inject(0) do |sum, i| > next if (i==3) > sum += i > done > > This breaks. If i is 3, then when the next occurs, the value of the > block is nil. The value of the block is added to sum, but because "+" > isn't defined for nil, there's an exception. Note that this isn't due to > the line "sum += i"; it's due to the design of inject: the value of the > block is added to sum. > > The real problem is that 'inject' has two semantics: 1) it adds onto sum > using an explicit "sum +=" or 2) is adds the value of the block. A > better approach would be allow only one way to accumulate. That way, you > can't make a change that inexplicitly changes the function from one > semantics to another. > > > -- > Posted via http://www.ruby-forum.com/. > > I agree using next with inject can be dangerous and probably should be avoided. You can however get round it by just returning the original value of sum when the condition is met: arr.inject do |sum,i| (sum==3) ? sum : sum + i end Farrel