Cosa significa to_proc method?

Sto imparando le rotaie e seguendo questo thread . Sono bloccato con il metodo to_proc . Considero i simboli solo come alternative alle stringhe (sono come gli archi ma meno costosi in termini di memoria). Se c’è qualcos’altro che mi manca per i simboli, quindi per favore dimmelo. Spiega in modo semplice cosa significa to_proc e a cosa serve.

Alcuni metodi prendono un blocco e questo schema appare spesso per un blocco:

 {|x| x.foo} 

e la gente vorrebbe scriverlo in un modo più conciso. Per fare ciò, un simbolo, il metodo Symbol#to_proc , il casting di class implicito e l’operatore & sono usati in combinazione. Se metti & davanti a un’istanza Proc nella posizione dell’argomento, questo verrà interpretato come un blocco. Se combinate qualcosa di diverso da un’istanza di Proc con & , il casting di class implicito tenterà di convertirlo in un’istanza di Proc usando il metodo to_proc definito su quell’object se ce n’è uno. In caso di un’istanza Symbol , to_proc funziona in questo modo:

 :foo.to_proc # => ->x{x.foo} 

Ad esempio, supponi di scrivere così:

 bar(&:foo) 

L’operatore & è combinato con :foo , che non è un’istanza di Proc , quindi il cast di class implicito applica Symbol#to_proc ad esso, che fornisce ->x{x.foo} . Il & si applica a questo ed è interpretato come un blocco, che fornisce:

 bar{|x| x.foo} 

Il modo più semplice per spiegarlo è con alcuni esempi.

 (1..3).collect(&:to_s) #=> ["1", "2", "3"] 

Equivale a:

 (1..3).collect {|num| num.to_s} #=> ["1", "2", "3"] 

e

 [1,2,3].collect(&:succ) #=> [2, 3, 4] 

Equivale a:

 [1,2,3].collect {|num| num.succ} #=> [2, 3, 4] 

to_proc restituisce un object Proc che risponde al metodo dato per simbolo. Quindi nel terzo caso, l’array [1,2,3] chiama il suo metodo collect e. succ è il metodo definito dalla class Array. Quindi questo parametro è un modo breve per dire di raccogliere ogni elemento nell’array e restituire il suo successore e da questo creare un nuovo array che risulta in [2,3,4]. Il simbolo: succ viene convertito in un object Proc in modo da chiamare il metodo succ di Array.

Per me la spiegazione più chiara è vedere una semplice implementazione di esso. Ecco come potrebbe essere se reimplementassi Symbol # to_proc:

 class Symbol # reopen Symbol class to reimplement to_proc method def to_proc ->(object) { object.send(self) } end end my_lambda = :to_s.to_proc puts my_lambda.(1) # prints '1'; .() does the same thing as .call() puts my_lambda.(1).class # prints 'String' puts [4,5,6].map(&:to_s) # prints "4\n5\n6\n" puts [4,5,6].map(&:to_s).first.class # prints 'String' 

Per qualcuno ancora un po ‘perplesso, l’esecuzione del seguente codice potrebbe rendere le cose un po’ più chiare:

 class Symbol def to_proc proc do |obj| puts "Symbol proc: #{obj}.send(:#{self})" obj.send(self) end end end class Array def map(&block) copy = self.class.new self.each do |index| puts "Array.map: copy << block.call(#{index})" copy << block.call(index) end copy end end remapped_array = [0, 1, 2].map &:to_s puts "remapped array: #{remapped_array.inspect}" 

Queste non sono le reali implementazioni di Symbol.to_proc o Array.map , sono solo versioni semplificate che sto usando per dimostrare come funzionano le map &:to_s e simili.