Puissance et principe du case en Ruby
En Ruby le statement case est capable de proposer de multiple usages
Usage générique
def test(x)
case x
when 1..5
"valeur entre 1 et 5"
when 6
"valeur = à 6"
when "foo", "bar"
"soit foo ou bar"
when /test/
"c'est un test"
when String
"c'est une String"
else
"c'est #{x} -- je ne sais pas quoi faire avec ."
end
end
[4, 6, "foo", "test","string", 10].each { |item| p test item}
Sortie :
"valeur entre 1 et 5"
"valeur = à 6"
"soit foo ou bar"
"c'est une String"
"c'est 10 -- je ne sais pas quoi faire avec ."
On voit que le case Ruby supporte :
- l'hétérogénéité des contrôles
- possède une action par défaut
- que la premier when qui match break le contrôle
mais comment ça marche ?
En fait chaque when execute la méthode #=== sur le motif du when avec pour paramètre le motif du case
En gros, pour
case x
when 1..5
"return"
end ou aurai le pseudo code :
"return" if 1..5.=== x
Remarque :
la méthode#===est définie surObjectetKernelet donc sur tout objet et chaque classe en Ruby
Elle est surchargée par chaque Classe pour être exploitable par case.
Un peu plus loin
Proc implémente aussi #===
et miracle il alias #call donc on peu faire des cases avec des Proc du genre :
impair= proc(&:odd?)
pair = proc(&:even?)
nombre = 12
case nombre
when impair
puts "nombre impair"
when pair
puts "nombre pair"
end
la sortie est :
nombre pairvoir Usage de l'ampersand dans une méthode pour comprendre la syntaxe : &:sym
Anti-pattern
Un case n'est pas une map, donc le translation symétrique ne doit pas être faite avec un case
Mauvais usage
item = "clef2"
res = case item
when "clef1"
"valeur1"
when "clef2"
"valeur2"
end
p res Oui, ça rappelle un Hash, donc :
Bonne usage
item = "clef1"
ITEMS = {
"clef1" => "valeur1",
"clef2" => "valeur2"
}
p ITEMS[item] Si on fait un case on à le risque sur un gros statement de faire le contrôle sur l'ensemble des règles, alors que de l'autre côté c'est juste un hashage.
On oublie pas que when est en fait un appelle de méthode !