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 surObject
etKernel
et 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 pair
voir 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 !