J'apprends Rails et suivants ce fil . Je suis coincé avec le to_proc
méthode. Je considère les symboles uniquement comme des alternatives aux chaînes (ils sont comme des chaînes mais moins chers en termes de mémoire). S'il me manque quelque chose d'autre pour les symboles, alors dites-le moi. Veuillez expliquer de manière simple ce que to_proc
signifie et à quoi il sert.
Certaines méthodes prennent un bloc, et ce modèle apparaît fréquemment pour un bloc:
{|x| x.foo}
et les gens aimeraient écrire cela de manière plus concise. Pour ce faire, un symbole, la méthode Symbol#to_proc
, transtypage de classe implicite et &
Les opérateurs sont utilisés en combinaison. Si vous mettez &
devant une instance de Proc
dans la position de l'argument, qui sera interprétée comme un bloc. Si vous combinez autre chose qu'une instance de Proc
avec &
, puis le transtypage de classe implicite tentera de convertir cela en une instance de Proc
en utilisant to_proc
méthode définie sur cet objet s'il y en a. Dans le cas d'une instance Symbol
, to_proc
fonctionne de cette façon:
:foo.to_proc # => ->x{x.foo}
Par exemple, supposons que vous écriviez comme ceci:
bar(&:foo)
Le &
L'opérateur est combiné avec :foo
, qui n'est pas une instance de Proc
, donc le transtypage de classe implicite s'applique Symbol#to_proc
, ce qui donne ->x{x.foo}
. Le &
s'applique maintenant à cela et est interprété comme un bloc, ce qui donne:
bar{|x| x.foo}
La façon la plus simple d'expliquer cela est avec quelques exemples.
(1..3).collect(&:to_s) #=> ["1", "2", "3"]
Est le même que:
(1..3).collect {|num| num.to_s} #=> ["1", "2", "3"]
et
[1,2,3].collect(&:succ) #=> [2, 3, 4]
Est le même que:
[1,2,3].collect {|num| num.succ} #=> [2, 3, 4]
to_proc renvoie un objet Proc qui répond à la méthode donnée par un symbole. Donc dans le troisième cas, le tableau [1,2,3] appelle sa méthode collect et. succ est une méthode définie par la classe Array. Donc, ce paramètre est une façon courte de dire de collecter chaque élément du tableau et de renvoyer son successeur et de créer un nouveau tableau qui donne [2,3,4]. Le symbole: succ est en cours de conversion en objet Proc, il appelle donc la méthode succ du tableau.
Pour moi, l'explication la plus claire est d'en voir une simple mise en œuvre. Voici à quoi cela pourrait ressembler si je réimplémentais le symbole # 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'
Pour quelqu'un encore un peu perplexe, l'exécution du code suivant pourrait rendre les choses un peu plus claires:
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}"
Ce ne sont pas les implémentations réelles de Symbol.to_proc
ou Array.map
, ce ne sont que des versions simplifiées que j'utilise pour montrer comment map &:to_s
et les appels similaires fonctionnent.