Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does this ruby injection magic work?

Tags:

ruby

I saw a ruby code snippet today.

[1,2,3,4,5,6,7].inject(:+)  

=> 28

[1,2,3,4,5,6,7].inject(:*)  

=> 5040

The injection here is quite different from those I've seen before, like

[1,2,3,4,5,6,7].inject {|sum, x| sum + x}

Please explain how does it work?

like image 787
Zifei Tong Avatar asked Aug 11 '10 05:08

Zifei Tong


3 Answers

There's no magic, symbol (method) is just one of the possible parameters. This is from the docs:

  # enum.inject(initial, sym) => obj
  # enum.inject(sym)          => obj
  # enum.inject(initial) {| memo, obj | block }  => obj
  # enum.inject          {| memo, obj | block }  => obj

Ours case is the second one.

You can also rewrite it with traditional block:

op = :+   #  parameter of inject call
[1,2,3,4,5,6,7].inject {|sum, x| sum.send(op, x)} #  also returns 28

(to answer "how does it work" part)

like image 131
Nikita Rybak Avatar answered Oct 16 '22 14:10

Nikita Rybak


The :+ is a symbol representing the addition message. Remember that Ruby has a Smalltalk style where just about every operation is performed by sending a message to an object.

As discussed in great detail here, (1..100).inject(&:+) is valid syntax in earlier versions where Rails has added the to_proc extension to Symbol.

The ability to pass just a symbol into inject was new in 1.9 and backported into 1.8.7.

like image 34
Andy Dent Avatar answered Oct 16 '22 13:10

Andy Dent


As you can see in the docs, inject can take a block (like you're familiar with) or a symbol that represents the name of a binary operator. It's a useful shorthand for already-defined ops.

like image 25
J Cooper Avatar answered Oct 16 '22 14:10

J Cooper