Elixir Language
utilisation de base des clauses de garde
Recherche…
utilisations de base des clauses de garde
Dans Elixir, on peut créer plusieurs implémentations d'une fonction avec le même nom et spécifier des règles qui seront appliquées aux paramètres de la fonction avant d'appeler la fonction afin de déterminer l'implémentation à exécuter.
Ces règles sont marquées par le mot-clé when
et elles se situent entre le nom de la def function_name(params)
et le do
dans la définition de la fonction. Un exemple trivial:
defmodule Math do def is_even(num) when num === 1 do false end def is_even(num) when num === 2 do true end def is_odd(num) when num === 1 do true end def is_odd(num) when num === 2 do false end end
Disons que je lance Math.is_even(2)
avec cet exemple. Il existe deux implémentations de is_even
, avec des clauses de garde différentes. Le système les examinera dans l'ordre et exécutera la première implémentation où les paramètres satisfont à la clause de protection. Le premier spécifie que num === 1
qui n'est pas vrai, donc il passe au suivant. Le second spécifie que num === 2
, ce qui est vrai, c'est donc l'implémentation utilisée et la valeur de retour sera true
.
Et si je lance Math.is_odd(1)
? Le système examine la première implémentation et constate que, puisque num
est 1
la clause guard de la première implémentation est satisfaite. Il utilisera alors cette implémentation et renverra true
, sans avoir à chercher d'autres implémentations.
Les gardes sont limités dans les types d'opérations qu'ils peuvent exécuter. La documentation Elixir répertorie toutes les opérations autorisées . en bref, ils permettent des comparaisons, des opérations mathématiques, des opérations binaires, une vérification de type (par exemple, is_atom
) et une poignée de petites fonctions pratiques (par exemple, la length
). Il est possible de définir des clauses de garde personnalisées, mais cela nécessite la création de macros et il est préférable de laisser un guide plus avancé.
Notez que les gardes ne jettent pas d'erreurs; ils sont traités comme des défaillances normales de la clause de protection et le système passe à la prochaine implémentation. Si vous trouvez (FunctionClauseError) no function clause matching
lors de l'appel d'une fonction protégée avec des paramètres que vous prévoyez de travailler, il se peut qu'une clause de protection que vous prévoyez utiliser génère une erreur qui est en train d'être avalée.
Pour voir cela par vous-même, créez puis appelez une fonction avec une garde qui n'a aucun sens, comme celle qui essaie de diviser par zéro:
defmodule BadMath do
def divide(a) when a / 0 === :foo do
:bar
end
end
L'appel de BadMath.divide("anything")
fournira l'erreur peu utile (FunctionClauseError) no function clause matching in BadMath.divide/1
- alors que si vous aviez essayé de lancer "anything" / 0
directement, vous obtiendriez une aide plus utile error: (ArithmeticError) bad argument in arithmetic expression
.