Rubino Proc Sintassi
-
12-10-2019 - |
Domanda
Una risposta a una domanda che ho posto ieri qui era il seguente pezzo di codice 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
ho each_cons
, ma qual è la strana notazione &:begin
? Salvami dalla sintassi inferno!
Grazie!
Soluzione
Quando si prefisso l'ultimo argomento di una chiamata con &
si stanno facendo chiaro che si sta inviando un blocco e non un normale argomento. Ok, in method(&:something)
, :something
è un simbolo, non un proc , in modo da Rubino chiama automaticamente il metodo to_proc
per ottenere un vero e proprio blocco. E Rails ragazzi (e ora anche la vaniglia Ruby) abilmente ha definito come:
class Symbol
def to_proc
proc { |obj, *args| obj.send(self, *args) }
end
end
È per questo che si può fare:
>> [1, 2, 3].map(&:to_s) # instead of [1, 2, 3].map { |n| n.to_s }
=> ["1", "2", "3"]
[modifica] Nota: quando ti rendi conto che questa costruzione è senza zucchero syntatic ma l'infrastruttura generica che Ruby fornisce, nulla vi impedisce di attuare il proprio to_proc
per le altre classi. Mai sentito limitato perché &:method
consentito alcun argomento?
class Array
def to_proc
proc { |obj, *args| obj.send(*(self + args)) }
end
end
>> ["1", "F", "FF"].map(&[:to_i, 16])
=> [1, 15, 255]
Altri suggerimenti
mezzi my_method(&some_value)
per invocare my_method
, passando some_value
nell'apposito alloggiamento argomento, il proc slot, solitamente riservato per il passaggio blocchi do-notazione.
my_block = lambda { puts "hello" }
(1..3).each(&my_block)
Qualsiasi oggetto che è un Proc
o che risponde al to_proc
è consentito da passare il proc-slot. Se si passa in un oggetto che non è un Proc
, ma che risponde alle to_proc
, poi di Ruby chiamerà to_proc
sull'oggetto per voi e per passare il risultato nel metodo.
L'attuazione di Symbol#to_proc
è quello di restituire un proc che, una volta superato un argomento, invia tale argomento il messaggio che è il simbolo stesso. Ad esempio, :hello.to_proc.call(my_obj)
finirà per fare my_obj.send :hello
.
Quindi my_array.each(&:hello)
passa :hello
al each
nel proc slot (dove un blocco normalmente passato, se si è utilizzato il do-notazione per fare un blocco). estremità :hello.to_proc.call(my_array[0])
per essere my_array[0].send :hello
, e lo stesso per tutti gli indici successivi my_array
.
è uguale a:
ranges.sort_by{|r| r.begin}