pass blocks argument ruby syntax block symbols proc

ruby - blocks - ¿Qué significa el método to_proc?



ruby pass block as argument (4)

Algunos métodos toman un bloque, y este patrón aparece frecuentemente para un bloque:

{|x| x.foo}

y a la gente le gustaría escribir eso de una manera más concisa. Para hacer eso, un símbolo, el método Symbol#to_proc , el lanzamiento de clase implícito y el operador & se usan en combinación. Si coloca & delante de una instancia de Proc en la posición de argumento, se interpretará como un bloque. Si combina algo que no sea una instancia de Proc con & , entonces la conversión de clase implícita intentará convertirla en una instancia de Proc utilizando el método to_proc definido en ese objeto, si existe alguno. En el caso de una instancia de Symbol , to_proc funciona de esta manera:

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

Por ejemplo, supongamos que escribes así:

bar(&:foo)

El operador & se combina con :foo , que no es una instancia de Proc , por lo que la Symbol#to_proc clase implícita aplica el Symbol#to_proc a él, lo que da ->x{x.foo} . El & ahora se aplica a esto y se interpreta como un bloque, que da:

bar{|x| x.foo}

Estoy aprendiendo rieles y siguiendo este hilo . Estoy atascado con el método to_proc . Considero los símbolos solo como alternativas a las cadenas (son como cadenas pero más baratas en términos de memoria). Si hay algo más que me falte para los símbolos, entonces dígame. Por favor explique de manera simple lo que significa to_proc y para qué se utiliza.


La forma más fácil de explicar esto es con algunos ejemplos.

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

Es lo mismo que:

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

y

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

Es lo mismo que:

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

to_proc devuelve un objeto Proc que responde al método dado mediante un símbolo. Entonces, en el tercer caso, la matriz [1,2,3] llama a su método de recolección y. succ es un método definido por la clase Array. Por lo tanto, este parámetro es una forma breve de decir, recopilar cada elemento de la matriz y devolver a su sucesor, y de ahí crear una nueva matriz que dé como resultado [2,3,4]. El símbolo: succ se está convirtiendo en un objeto Proc para que llame al método succ del Array.


Para alguien que todavía esté un poco perplejo, ejecutar el siguiente código podría aclarar un poco las cosas:

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}"

Estas no son las implementaciones reales de Symbol.to_proc o Array.map , solo son versiones simplificadas que estoy usando para demostrar cómo funcionan el map &:to_s y llamadas similares.


Para mí, la explicación más clara es ver una implementación simple de esto. Esto es lo que podría parecer si volviera a implementar el Símbolo # 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''