13

I find this code in Ruby to be pretty intriguing

(1..4).inject(&:+)

Ok, I know what inject does, and I know this code is basically equivalent to

(1..4).inject(0) {|a,n| a + n}

but how exactly does it work?

Why &:+ is the same as writing the block {|a,n| a + n}?

Why it doesn't need an initial value? I'm ok with the inicial value being 0, but (1..4).inject(&:*) also works, and there the initial value must be 1...

Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
Marcos Crispino
  • 8,018
  • 5
  • 41
  • 59
  • 8
    These are really two completely separate questions, the first one of which is a duplicate of no less than 11 other questions that have already been asked and answered here on StackOverflow: http://StackOverflow.Com/q/99318/ http://StackOverflow.Com/q/1217088/ http://StackOverflow.Com/q/1792683/ http://StackOverflow.Com/q/1961030/ http://StackOverflow.Com/q/2096975/ http://StackOverflow.Com/q/2211751/ http://StackOverflow.Com/q/2259775/ http://StackOverflow.Com/q/2388337/ http://StackOverflow.Com/q/2697024/ http://StackOverflow.Com/q/3888044/ http://StackOverflow.Com/q/4512587/ – Jörg W Mittag Feb 15 '11 at 18:46

1 Answers1

14

From Ruby documentation:

If you specify a symbol instead, then each element in the collection will be passed to the named method of memo

So, specifying a symbol is equivalent to passing the following block: {|memo, a| memo.send(sym, a)}

If you do not explicitly specify an initial value for memo, then uses the first element of collection is used as the initial value of memo.

So, there is no magic, Ruby simply takes the first element as the initial value and starts injecting from the second element. You can check it by writing [].inject(:+): it returns nil as opposed to [].inject(0, :+) which returns 0.

Edit: I didn't notice the ampersand. You don't need it, inject will work with a symbol. But if you do write it, the symbol is converted to block, it can be useful with other methods

Community
  • 1
  • 1
adamax
  • 3,835
  • 2
  • 19
  • 21
  • @tokland It's basically the same conversion but works with any method, the top answer at the linked question has a good explanation. – adamax Feb 15 '11 at 12:42