tags:

views:

59

answers:

3

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?

+4  A: 

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)

Nikita Rybak
Can't find information about symbol as parameters here, http://ruby-doc.org/core/classes/Enumerable.html. The doc is too old...
Zifei Tong
@Zifei That's the link to version 1.8.6. Check http://ruby-doc.org/ for links to other versions, Core API section
Nikita Rybak
Get it, http://ruby-doc.org/core-1.8.7/classes/Enumerable.html. Thanks.
Zifei Tong
+1  A: 

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.

J Cooper
Thanks, ruby 1.9 is sweet :)
Zifei Tong
+1  A: 

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.

Andy Dent