First, I'll just create a variable 'words' as an array of strings, so we can have something to work with.
words = %w{test hello world}
Starts to use this symbol, '&' = symbol-to-proc
words.map(&:upcase)
'&' is symbol-to-proc character, which means it interprets the following symbol(':upcase') with .to_proc()
words.map(&:upcase.to_proc)
If you look into the source code of Symbol.to_proc ('to_proc' method in 'Symbol' class), you'll find it returns something like this back.
words.map(&proc{|obj,*args| obj.send(:upcase,*args)})
Then, '&' convert the proc into a block (notice the braces).
words.map{|obj,*args| obj.send(:upcase,*args)}
Since, '.map' only provides one argument for a block. The *args is neglected.
words.map{|obj| obj.send(:upcase)}
'.send' is similarly called directly with the symbol.
words.map{|obj| obj.upcase}
The result is
=> ["TEST", "WORLD", "HELLO"]
Now, let's try it with a method with 2 arguments, such as '.inject'
Here are the normal ways that we can write inject with.
(1..10).inject(:+) #only with Ruby 1.9 (1..10).inject(&:+) (1..10).inject(0,:+) #only with Ruby 1.9 (1..10).inject(0,&:+) (1..10).inject{|result,element| result+element} (1..10).inject(0){|result,element| result+element}*whereas 0 is initial value of the summation
Now, the reduction of the '.inject'.
Starting from the basic one.
(1..10).inject(&:+)
with Symbol-to-proc, it interprets this symbol (':+') as it is a proc (or called with .to_proc)
(1..10).inject(&:+.to_proc)
What .to_proc does with a symbol is
(1..10).inject(&proc{|obj,*args| obj.send(:+,*args)})
Then, this proc becomes a block for .inject
(1..10).inject{|obj,*args| obj.send(:+,*args)}
Since '.inject' can have a block that takes 2 arguments, I'll rename the arguments as
(1..10).inject{|result,element| result.send(:+,element)}
So then, '.send' can be substituted with a direct call
(1..10).inject{|result,element| result.+(element)}
Or with out using dot (only for operators)
(1..10).inject{|result,element| result + element}
Finally, the result is
=> 55
** remark: every code line is syntactically correct.
Suggest For Further Watching/Readings:
- http://www.youtube.com/watch?v=aISNtCAZlMg
- http://phrogz.net/symbol-to-proc-with-multiple-arguments
- http://www.potstuck.com/2011/08/06/ruby-symbols-instead-of-blocks/
No comments:
Post a Comment