14 Jan 2010

Why I like Enumerable#inject

Recently I’ve been helping a friend learn Ruby. Digging around first year university assignments, I stumbled on a method definition for calculating the annual interest on a bank balance that’s compounded monthly.

The original implementation was in Java, which you could imagine would be more verbose.

def calculate_interest(rate)
  monthly_balance = @balance
  interest = 0
  12.times do
    monthly_interest = monthly_balance * rate
    interest = interest + monthly_interest
    monthly_balance = monthly_balance + monthly_interest
  end
  interest
end

Look at all those variables. Yuck. I would never write code like this today. Accumulation is a perfect candidate for Enumerable#inject.

def calculate_interest(rate)
  balance_plus_interest = 12.times.inject(@balance) do |balance, m| 
    balance += balance * rate
  end
  balance_plus_interest - @balance
end

Storing the result is unnecessary.

def calculate_interest(rate)
  12.times.inject(@balance) { |b, m| b += b * rate } - @balance
end

Although unnecessary, I’d argue it may lead to less readable code.

Lastly, while you’re not prevented from chaining method invocations to the end keyword, it doesn’t feel right. That said, I’m open to change.

def calculate_interest(rate)
  12.times.inject(@balance) do |balance, m| 
    balance += balance * rate
  end - @balance
end

← Previous
Next →

Tate Johnson is a 23 year old Ruby on Rails developer and university student living in Brisbane, Australia. He enjoys riding bicycles, motorbikes, taking photos and travelling.