Les structs sont une extension construite au-dessus des maps, qui apportent des vérifications à la compilation et des valeurs par défaut. Un struct porte le nom du module dans lequel il est défini. Pour définir un struct, on utilise la construction defstruct. Celle-ci suit généralement immédiatement la définition du module. defstruct accepte soit une liste d'atomes (pour des valeurs par défaut à nil), soit une liste de mots-clés (pour des valeurs par défaut spécifiques). Les champs sans valeur par défaut doivent venir avant ceux qui en ont une.
defmodule Plane do
defstruct [:engine, wings: 2]
end
plane = %Plane{}
# => %Plane{engine: nil, wings: 2}
Comme les structs sont construits sur des maps, on peut utiliser la plupart des fonctions associées aux maps pour obtenir et manipuler des valeurs. Le comportement Access n'est pas implémenté pour les structs. Il est recommandé d'utiliser plutôt l'opérateur d'accès statique . pour accéder aux champs d'un struct.
obtenir/récupérer les valeurs des champs :
plane = %Plane{}
plane.engine
# => nil
Map.fetch(plane, :wings)
# => {:ok, 2}
mettre à jour les valeurs des champs
plane = %Plane{}
%{plane | wings: 4}
# => %Plane{engine: nil, wings: 4}
Les structs peuvent être utilisés en filtrage par motif, avec ou sans le nom du struct.
plane = %Plane{}
%Plane{wings: wings} = plane
%{wings: wings} = plane
En incluant le nom du struct dans le motif, on s'assure que le côté gauche et le côté droit sont bien des structs du même type.
defmodule Helicopter do
defstruct [:engine, rotors: 1]
end
%Plane{} = %Helicopter{}
# => (MatchError) no match of right hand side value: %Helicopter{engine: nil, rotors: 1}
On peut utiliser l'attribut de module @enforce_keys avec une liste des clés de champ pour s'assurer que les valeurs sont initialisées à la création du struct. Si une clé n'est pas listée, sa valeur sera nil, comme dans l'exemple ci-dessus. Si une clé soumise à @enforce_keys n'est pas initialisée, une erreur est levée.
defmodule User do
@enforce_keys [:username]
defstruct [:username]
end
%User{}
# => (ArgumentError) the following keys must also be given when building struct User: [:username]
Dans cet exercice, tu vas jouer avec une voiture télécommandée, pour laquelle tu as enfin économisé assez d'argent pour l'acheter.
Les voitures commencent avec une batterie pleine (100 %). Chaque fois que tu conduis la voiture avec la télécommande, elle parcourt 20 mètres et consomme un pour cent de la batterie. Le surnom de la voiture n'est pas connu avant sa création.
La voiture télécommandée possède un écran LED sophistiqué qui affiche deux informations :
"<METERS> meters"."Battery at <PERCENTAGE>%".Si la batterie est à 0 %, tu ne peux plus conduire la voiture et l'affichage de la batterie affichera "Battery empty".
Implémente la fonction RemoteControlCar.new/0 pour renvoyer une toute nouvelle structure de voiture télécommandée :
RemoteControlCar.new()
# => %RemoteControlCar{
# battery_percentage: 100,
# distance_driven_in_meters: 0,
# nickname: "none"
# }
Le surnom est requis par la structure ; assure-toi qu'une valeur est initialisée dans la fonction new, mais pas dans la structure.
Implémente la fonction RemoteControlCar.new/1 pour renvoyer une toute nouvelle structure de voiture télécommandée avec un surnom fourni :
RemoteControlCar.new("Blue")
# => %RemoteControlCar{
# battery_percentage: 100,
# distance_driven_in_meters: 0,
# nickname: "Blue"
# }
Implémente la fonction RemoteControlCar.display_distance/1 pour renvoyer la distance telle qu'affichée sur l'écran LED :
car = RemoteControlCar.new()
RemoteControlCar.display_distance(car)
# => "0 meters"
Assure-toi que la fonction n'accepte qu'une structure RemoteControlCar comme argument.
Implémente la fonction RemoteControlCar.display_battery/1 pour renvoyer le pourcentage de batterie tel qu'affiché sur l'écran LED :
car = RemoteControlCar.new()
RemoteControlCar.display_battery(car)
# => "Battery at 100%"
Assure-toi que la fonction n'accepte qu'une structure RemoteControlCar comme argument. Si la batterie est à 0 %, l'affichage de la batterie affichera "Battery empty".
Implémente la fonction RemoteControlCar.drive/1 qui :
RemoteControlCar.new("Red")
|> RemoteControlCar.drive()
# => %RemoteControlCar{
# battery_percentage: 99,
# distance_driven_in_meters: 20,
# nickname: "Red"
# }
Assure-toi que la fonction n'accepte qu'une structure RemoteControlCar comme argument.
Mets à jour la fonction RemoteControlCar.drive/1 pour qu'elle n'augmente pas la distance parcourue et ne diminue pas le pourcentage de batterie lorsque la batterie est déchargée (à 0 %) :
%RemoteControlCar{
battery_percentage: 0,
distance_driven_in_meters: 1980,
nickname: "Red"
}
|> RemoteControlCar.drive()
# => %RemoteControlCar{
# battery_percentage: 0,
# distance_driven_in_meters: 1980,
# nickname: "Red"
# }
Inscris-toi sur Exercism pour apprendre et maîtriser Elixir avec 58 concepts168 exercices, et un vrai mentorat humain, le tout gratuitement.