¿Qué significa el método to proc?
Estoy aprendiendo rails 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 falta para los símbolos, entonces por favor dime. Por favor, explique de manera sencilla lo que significa to_proc
y para qué se utiliza.
4 answers
Algunos métodos toman un bloque, y este patrón aparece con frecuencia 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 casting implícito de clase y el operador &
se usan en combinación. Si coloca &
delante de una instancia Proc
en la posición del argumento, se interpretará como un bloque. Si combina algo que no sea una instancia Proc
con &
, entonces la transmisión de clase implícita intentará convierta eso a una instancia Proc
usando el método to_proc
definido en ese objeto si hay alguno. En el caso de una instancia 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 Proc
, por lo que implicit class cast le aplica Symbol#to_proc
, lo que da ->x{x.foo}
. El &
ahora se aplica a esto y se interpreta como un bloque, que da:
bar{|x| x.foo}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-14 19:06:39
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 por símbolo. Así que en el tercer caso, la matriz [1,2,3] llama a su método de recogida y. succ es el método definido por la matriz de clases. Así que este parámetro es una forma corta de decir recoger cada elemento en la matriz y devolver su sucesor y a partir de eso crear una nueva matriz lo que resulta en [2,3,4]. El símbolo: succ se está convirtiendo en un objeto Proc por lo que llama al método succ de la matriz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-14 18:38:23
Para mí la explicación más clara es ver una simple implementación de la misma. Esto es lo que podría parecer si estuviera reimplementando 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'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-10 07:59:48
Para cualquiera que todavía esté un poco perplejo, ejecutar el siguiente código podría hacer las cosas un poco más claras:
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
, son solo versiones simplificadas que estoy usando para demostrar cómo funcionan map &:to_s
y llamadas similares.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-26 05:48:58