Pregunta
Una respuesta a una pregunta que hice ayer aquí fue el siguiente fragmento de código Ruby:
def overlap?(r1,r2)
r1.include?(r2.begin) || r2.include?(r1.begin)
end
def any_overlap?(ranges)
ranges.sort_by(&:begin).each_cons(2).any? do |r1,r2|
overlap?(r1, r2)
end
end
consigo each_cons
, pero ¿cuál es la notación &:begin
extraño? Sálvame de sintaxis demonios!
Gracias!
Solución
Cuando se anteponga el último argumento de una llamada con &
usted está haciendo evidente que usted está enviando un bloque y no un Normal argumento. Ok, en method(&:something)
, :something
es un símbolo, no un proc , por lo Rubí llama automáticamente al to_proc
método para obtener un bloque real. Y los carriles chicos (y ahora también de vainilla Rubí) hábilmente definió como:
class Symbol
def to_proc
proc { |obj, *args| obj.send(self, *args) }
end
end
Es por eso que puede hacer:
>> [1, 2, 3].map(&:to_s) # instead of [1, 2, 3].map { |n| n.to_s }
=> ["1", "2", "3"]
[editar] Nota: cuando se da cuenta de que esta construcción es sin azúcar sintáctico pero la infraestructura genérica que ofrece Rubí, nada le impide la implementación de su propia to_proc
para otras clases. Nunca me sentí limitado debido &:method
permitió sin argumentos?
class Array
def to_proc
proc { |obj, *args| obj.send(*(self + args)) }
end
end
>> ["1", "F", "FF"].map(&[:to_i, 16])
=> [1, 15, 255]
Otros consejos
my_method(&some_value)
medios para invocar my_method
, pasando some_value
en la ranura argumento especial, el proc-ranura, normalmente reservado para el paso de los bloques do-notación.
my_block = lambda { puts "hello" }
(1..3).each(&my_block)
Cualquier objeto que es una Proc
o que responde a to_proc
se permite ser pasado en el proc-ranura. Si se pasa en un objeto que no es un Proc
pero que responde a to_proc
, a continuación, Rubí llamará to_proc
en el objeto para usted y pasar el resultado en el método.
La implementación de Symbol#to_proc
es devolver un proc que, una vez transcurrido un argumento, envía ese argumento el mensaje de que es el símbolo en sí mismo. Por ejemplo, :hello.to_proc.call(my_obj)
va a terminar haciendo my_obj.send :hello
.
Así my_array.each(&:hello)
pasa a :hello
each
en el proc-ranura (donde un bloque normalmente pasado, si ha utilizado la notación hacer para que un bloque). extremos :hello.to_proc.call(my_array[0])
siendo my_array[0].send :hello
, y la misma para todos los índices subsiguientes de my_array
.
es igual a:
ranges.sort_by{|r| r.begin}