Question

Une réponse à une question que je posais hier ici était la pièce de code suivante 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

Je reçois each_cons, mais quelle est la notation &:begin étrange? Sauve-moi de l'enfer de syntaxe!

Merci!

Était-ce utile?

La solution

Lorsque vous préfixe le dernier argument d'un appel avec & vous indiquant clairement que vous envoyez un bloc et non normale argument. Ok, dans method(&:something), :something est un symbole, pas proc , si Ruby appelle automatiquement la méthode to_proc pour obtenir un vrai bloc. Et les gars Rails (et maintenant la vanille Ruby) intelligemment définie comme:

class Symbol
  def to_proc
    proc { |obj, *args| obj.send(self, *args) }
  end
end

C'est pourquoi vous pouvez faire:

>> [1, 2, 3].map(&:to_s) # instead of [1, 2, 3].map { |n| n.to_s }
=> ["1", "2", "3"]

[modifier] Remarque: lorsque vous vous rendez compte que cette construction est sans sucre, mais l'infrastructure générique syntactique que Ruby fournit, rien ne vous empêche de mettre en œuvre votre propre to_proc pour les autres classes. Jamais senti limité parce &:method permis pas d'arguments?

class Array
  def to_proc
    proc { |obj, *args| obj.send(*(self + args)) }
  end
end

>> ["1", "F", "FF"].map(&[:to_i, 16])
=> [1, 15, 255]

Autres conseils

moyens de my_method(&some_value) pour invoquer my_method, en passant dans la fente some_value argument particulier, la fente de proc, habituellement réservé pour le passage des blocs de notation do.

my_block = lambda { puts "hello" }
(1..3).each(&my_block)

Tout objet qui est un Proc ou qui répond à to_proc est autorisé à passer dans la fente de proc. Si vous passez dans un objet qui n'est pas Proc mais qui répond à to_proc, puis Ruby appellera to_proc sur l'objet pour vous et passer le résultat dans la méthode.

La mise en œuvre de Symbol#to_proc est de renvoyer un proc qui, lorsqu'il est passé un argument, envoie cet argument, le message qui est le symbole lui-même. Par exemple, :hello.to_proc.call(my_obj) va finir par faire my_obj.send :hello.

my_array.each(&:hello) passe :hello à each dans la fente de proc (où un bloc normalement passé, si vous avez utilisé la notation faire pour un bloc). se termine :hello.to_proc.call(my_array[0]) jusqu'à être my_array[0].send :hello, et même pour tous les indices suivants de my_array.

il est égal à:

ranges.sort_by{|r| r.begin}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top