Cosa sono: + e &: + in Ruby?

Li ho visti diverse volte ma non riesco a capire come usarli. Il piccone dice che si tratta di scorciatoie speciali ma non sono riuscito a trovare la descrizione sintattica.

Li ho visti in questi contesti:

[1,2,3].inject(:+) 

per calcolare la sum, per esempio.

Iniziamo con un esempio più semplice. Diciamo che abbiamo una serie di stringhe che vogliamo avere in maiuscolo:

 ['foo', 'bar', 'blah'].map { |e| e.upcase } # => ['FOO', 'BAR', 'BLAH'] 

Inoltre, puoi creare i cosiddetti oggetti Proc (chiusure):

 block = proc { |e| e.upcase } block.call("foo") # => "FOO" 

Puoi passare tale proc a un metodo con & syntax:

 block = proc { |e| e.upcase } ['foo', 'bar', 'blah'].map(&block) # => ['FOO', 'BAR', 'BLAH'] 

Ciò che fa è chiamare to_proc sul blocco e quindi chiama quello per ogni blocco:

 some_object = Object.new def some_object.to_proc proc { |e| e.upcase } end ['foo', 'bar', 'blah'].map(&some_object) # => ['FOO', 'BAR', 'BLAH'] 

Ora, Rails ha prima aggiunto il metodo to_proc a Symbol, che in seguito è stato aggiunto alla libreria core di ruby:

 :whatever.to_proc # => proc { |e| e.whatever } 

Pertanto puoi farlo:

 ['foo', 'bar', 'blah'].map(&:upcase) # => ['FOO', 'BAR', 'BLAH'] 

Inoltre, Symbol # to_proc è ancora più intelligente, poiché in realtà procede come segue:

 :whatever.to_proc # => proc { |obj, *args| obj.send(:whatever, *args) } 

Ciò significa che

 [1, 2, 3].inject(&:+) 

equivale

 [1, 2, 3].inject { |a, b| a + b } 

iniettare accetta un simbolo come parametro, questo simbolo deve essere il nome di un metodo o operatore, che in questo caso è :+

quindi [1,2,3].inject(:+) sta passando ogni valore al metodo specificato dal simbolo, quindi sumndo tutti gli elementi nella matrice.

fonte: https://ruby-doc.org/core-2.5.1/Enumerable.html