What are :+ and &:+ in Ruby?
I've seen these several times but I can't figure out how to use them. The pickaxe says that these are special shortcuts but I wasn't able to find the syntactical description.
I've seen them in such conte开发者_Python百科xts:
[1,2,3].inject(:+)
to calculate sum for example.
Let's start with an easier example. Say we have an array of strings we want to have in caps:
['foo', 'bar', 'blah'].map { |e| e.upcase }
# => ['FOO', 'BAR', 'BLAH']
Also, you can create so called Proc objects (closures):
block = proc { |e| e.upcase }
block.call("foo") # => "FOO"
You can pass such a proc to a method with the & syntax:
block = proc { |e| e.upcase }
['foo', 'bar', 'blah'].map(&block)
# => ['FOO', 'BAR', 'BLAH']
What this does, is call to_proc on block and then calls that for every block:
some_object = Object.new
def some_object.to_proc
proc { |e| e.upcase }
end
['foo', 'bar', 'blah'].map(&some_object)
# => ['FOO', 'BAR', 'BLAH']
Now, Rails first added the to_proc method to Symbol, which later has been added to the ruby core library:
:whatever.to_proc # => proc { |e| e.whatever }
Therefore you can do this:
['foo', 'bar', 'blah'].map(&:upcase)
# => ['FOO', 'BAR', 'BLAH']
Also, Symbol#to_proc is even smarter, as it actually does the following:
:whatever.to_proc # => proc { |obj, *args| obj.send(:whatever, *args) }
This means that
[1, 2, 3].inject(&:+)
equals
[1, 2, 3].inject { |a, b| a + b }
inject accepts a symbol as a parameter, this symbol must be the name of a method or operator, which is this case is :+
so [1,2,3].inject(:+)
is passing each value to the method specified by the symbol, hence summing all elements in the array.
source: https://ruby-doc.org/core-2.5.1/Enumerable.html
精彩评论