One of the things I love most about Ruby is the simple extensible ways you can manipulate objects. So when I recently came across a new instance of this, I thought I'd pass it along to my readers. I decided to write a framework for working with pen and paper games, and when I started writing the dice rolling class I noticed that I had a block that had to be unnecessary in Ruby.
num.times { rolls << (rand(dtype)+1) }
sum = 0
rolls.each do |r|
sum += r
end
The first line is just rolling the dice a specified number of times and loading them into the rolls array that I previously declared. The rest of it is just adding up all the numbers to return a sum. Being a former Java programmer this is exactly how I would have done it there, so I just wrote it that way and moved on. But as I began to look back, I realized that it was quite ugly. Beyond that, I couldn't believe that Ruby wouldn't have a more elegant way to handle this common task of reducing an array of components to a final result. Fortunately it does, and the answer is in the inject and reduce methods.
These two methods appear to be identical as far as I can see (if I'm wrong, then feel free to correct me in the comments and I'll edit this later), so I'll be addressing just reduce, since I find it more pleasing syntacitcally. So using these how can I solve my problem?
rolls.reduce(:+)
One tiny line. I love me some Ruby. Reduce actually performs an identical operation on each element of the array, keeping a carryover variable as it does so. For simple mathmatical operations, you can pass a symbol of the operator you want to use, like :+ to add everyone up. But you can also use other operators, even :** if you wanted the code to exponentially increase on every iteration. However, what if you have an array of strings you'd like to get specific data out of with a constant operation. Or what if you want to do a little more complex operation to each one. Well as usual, blocks come to the rescue.
rolls.reduce { |total, n| (total + n) * -1 }
rolls.reduce { |highest, n| highest > n ? highest : n }
The first one does a more complex operation, multiplying the result by -1 every time. It's contrived, but it shows how you can give the array a block of more complex math. The second example iterates through the array comparing the elements looking for the largest item in the array. It should be noted that the return value from the block becomes the new carried variable, and the final returned variable is the return from the method. Also note this doesn't change the value of the array.
Hopefully someone else will find that this saves them some time later!