case

Un case est une expression qui permet une sorte de correspondance par motif. Elle permet d'écrire une chaîne de if-else-if avec une légère différence sémantique et quelques structures puissantes supplémentaires.

Dans sa forme basique, elle permet de faire correspondre une valeur avec d'autres valeurs:

case exp
when valeur1, valeur2
  faire_quelque_chose
when value3
  faire_quelque_chose_autre
else
  faire_encore_autre_chose
end

# L'exemple précédent est équivalent à:
tmp = exp
if value1 === tmp || value2 === tmp
  faire_quelque_chose
elsif value3 === tmp
  faire_encore_autre_chose
else
  faire_encore_autre_chose
end

Remarquez que === est utilisé pour comparer une expression par rapport à une valeur d'un case. Il est défini comme une méthode sur Object et peut être remplacé par des sous-classes pour fournir une sémantique significative dans les déclarations de cas. Par exemple, Class définit l'égalité des cas comme lorsque l'objet est une instance de cette classe, Regex comme lorsque la valeur correspond à la normale expression et Range comme lorsque la valeur est incluse dans ce champ.

Si l'expression d'un when est un type, is_a? est utilisé. De plus, si l'expression du case est une variable ou une affectation de variable le type de cette variable est restreint:

case var
when String
  # var : String
  faire_quelque_chose
when Int32
  # var : Int32
  faire_encore_autre_chose
else
  # ici var est ni une String ni un Int32
  faire_encore_autre_chose
end

# L'exemple précédent est équivalent à:
if var.is_a?(String)
  faire_quelque_chose
elsif var.is_a?(Int32)
  faire_encore_autre_chose
else
  faire_encore_autre_chose
end

Vous pouvez invoquer une méthode comme expression du case dans un when en utilisant la syntaxe d'objet implicite:

case num
when .even?
  faire_quelque_chose
when .odd?
  faire_encore_autre_chose
end

# L'exemple précédent est équivalent à:
tmp = num
if tmp.even?
  faire_quelque_chose
elsif tmp.odd?
  faire_encore_autre_chose
end

Enfin, vous pouvez omettre la valeur du case:

case
when cond1, cond2
  faire_quelque_chose
when cond3
  faire_encore_autre_chose
end

# L'exemple précédent est équivalent à:
if cond1 || cond2
  faire_quelque_chose
elsif cond3
  faire_encore_autre_chose
end

Cela permet parfois d'écrire du code plus naturel à lire.

Litéral de tuple

Quand l'expression d'un case est un litéral de tuple il y a quelques différences sémantiques si la condition du when est aussi un litéral de tuple.

La taille du tuple doit correspondre

case {value1, value2}
when {0, 0} # OK, 2 éléments
  # ...
when {1, 2, 3} # Erreur du compilateur, correspondance impossible
  # ...
end

Souligné autorisé

case {value1, value2}
when {0, _}
  # Correspondance si 0 === value1, aucun test sur value2
when {_, 0}
  # Correspondance si 0 === value2, aucun test sur value1
end

Objet implicite autorisé

case {value1, value2}
when {.even?, .odd?}
  # Correspondance si value1.even? && value2.odd?
end

Une comparaison sur un type va exécuter une vérification avec is_a?

case {value1, value2}
when {String, Int32}
  # Correspondance si value1.is_a?(String) && value2.is_a?(Int32)
  # Le type de value1 est connu comme étant String par le compilateur,
  # et le type de value2 comme étant Int32
end

results matching ""

    No results matching ""