Pourquoi les procs peuvent-ils être invoqués avec === dans Ruby 1.9 ?
-
12-12-2019 - |
Question
Cet article mentionne 4 façons d'invoquer des procs dans Ruby 1.9, et === en fait partie.Je ne comprends pas du tout pourquoi cela se ferait de cette façon.Cela a-t-il un rapport avec la signification normale de === (demander si les deux objets sont le même objet) ?
irb(main):010:0> f =-> n {[:hello, n]} => # irb(main):011:0> f.call(:hello) => [:hello, :hello] irb(main):012:0> f === :hello => [:hello, :hello] irb(main):013:0> Object.new === Object.new => false irb(main):014:0> f === f => [:hello, #]
La solution
C'est ce que disent les documents:
Il s'agit de permettre à un objet proc d'être la cible de
when
clause dans la déclaration de cas.
Ceci est un exemple, peut-être artificiel :
even = proc { |x| x % 2 == 0 }
n = 3
case n
when even
puts "even!"
else
puts "odd!"
end
Cela fonctionne parce que le case/when
est essentiellement exécuté comme ceci :
if even === n
puts "even!"
else
puts "odd!"
end
Le case/when
vérifie quelle branche exécuter en appelant ===
sur les arguments à when
clauses, en choisissant la première qui renvoie une valeur véridique.
Malgré sa similitude avec l'opérateur d'égalité (==
) ce n’est pas une forme plus forte ou plus faible.J'essaie de penser à ===
comme opérateur "appartient à". Class
le définit afin que vous puissiez vérifier si un objet appartient à la classe (c'est-à-direest une instance de la classe ou une sous-classe de la classe), Range
le définit comme pour vérifier si l'argument appartient à la plage (c'est-à-direest inclus dans la gamme), et ainsi de suite.Cela ne rend pas vraiment le Proc
cas a plus de sens, mais considérez-le comme un outil pour créer le vôtre appartient à opérateurs, comme mon exemple ci-dessus ;J'ai défini un objet qui peut déterminer si quelque chose appartient à l'ensemble des nombres pairs.
Autres conseils
Notez que ===
dans Ruby ne concerne pas l'égalité, contrairement à JavaScript.Il est spécifiquement utilisé pour les expressions de cas :
case cats.length
when 42 # Uses 42 === cats.length
puts :uh
when /cool/i # Uses /cool/i === cats.length
puts :oh
when ->(n){ n.odd? || n/3==6 } # Passes cats.length to the proc
puts :my
end
Cette fonctionnalité est utile dans le cas de la construction, lorsque vous devez calculer quelque chose à la comparaison.
is_odd =-> n { n%2 != 0 }
is_even =-> n { n%2 == 0 }
case 5
when is_even
puts "the number is even"
when is_odd
puts "the number is odd"
end
=> the number is odd
Cela a-t-il un rapport avec la signification normale de === (demander si les deux objets sont le même objet) ?
En fait, c'est une idée fausse très répandue à propos ===
en Rubis.En fait, ce n'est pas strictement destiné Object#object_id
comparaison (bien que ce soit son comportement dans de nombreuses invocations courantes).En Rubis, ===
c'est le cas subsomption.
Voici la description de ===
depuis Object
:"Égalité de cas - pour l'objet de classe, en fait la même chose que l'appel # ==, mais généralement remplacé par les descendants de fournir une sémantique significative dans les instructions de cas."
Malheureusement, même s'il comprend trois =
, cela n'a rien à voir, même de loin, avec l'égalité :-D