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!

È stato utile?

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}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top