Module Elixir avec structure et fonctions

Nous souhaitons construire des modules Elixir avec à la fois une structure et des fonctions manipulant la structure.

Commençons par regarder la documentation officielle pour les Modules et les Structure.

Erreur « struct/0 is undefined »

Si nous créons une structure dans un module avec des fonctions dans ce même module comme l’exemple ci-dessous, nous avons une erreur « struct/0 is undefined » indiquée à l’emplacement de l’utilisation de la structure dans la fonction, sur « %Person » ligne 8.

Voilà le code en erreur :

defmodule Person do
  @moduledoc """
  Module pour représenter une personne avec des fonctions pour accéder à ses propriétés.
  """

  defstruct [:name, :age, :email]

  def get_name(%Person{name: name}), do: name
  def get_age(%Person{age: age}), do: age
  def get_email(%Person{email: email}), do: email
end

Message d’erreur à la compilation :

Compiling 1 file (.ex)
    error: Person.__struct__/0 is undefined, cannot expand struct Person. Make sure the struct name is correct. If the struct name exists and is correct but it still cannot be found, you likely have cyclic module usage in your code
    │
  8 │   def get_name(%Person{name: name}), do: name
    │                ^
    │
    └─ lib/my_app.person.ex:8:16: MyApp.Person.get_name/1

Erreur sur un module elixir avec structure et fonctions

La préconisation proposée dans ce paragraphe ne donne aucune piste pour corriger l’erreur indiquée à la compilation.

L’erreur que vous rencontrez lors de la compilation, indiquant que Person.__struct__/0 is undefined, suggère que la structure Person n’est pas reconnue au moment où elle est utilisée. Cela peut être dû à plusieurs raisons, notamment une erreur dans la définition de la structure ou un problème de dépendances cycliques. Voici quelques étapes pour résoudre ce problème :

1. Vérifier la définition de la structure

Assurez-vous que la structure Person est correctement définie dans le module Chatracs.Plugset.Message.Person. La définition de la structure doit précéder toute utilisation de %Person{} dans le module. Voici un exemple de définition correcte :

defmodule Chatracs.Plugset.Message.Person do
  @moduledoc """
  Module pour représenter une personne avec des fonctions pour accéder à ses propriétés.
  """

  defstruct [:name, :age, :email]

  def get_name(%Person{name: name}), do: name
  def get_age(%Person{age: age}), do: age
  def get_email(%Person{email: email}), do: email
end

2. Vérifier l’ordre des déclarations

Assurez-vous que toutes les fonctions ou alias utilisés dans le module sont déclarés après la définition de la structure. Par exemple, si vous utilisez des alias pour d’autres modules ou des fonctions qui manipulent Person, ces déclarations doivent suivre la définition de defstruct.

3. Vérifier les dépendances cycliques

Examinez si Person ou les modules qu’il utilise ne créent pas de dépendances cycliques. Par exemple, si un module A utilise B et B utilise A, cela peut causer des problèmes de compilation. Essayez de restructurer votre code pour éliminer ces dépendances.

4. Compiler avec des informations détaillées

Utilisez MIX_DEBUG=1 mix compile pour obtenir plus d’informations sur le processus de compilation. Cela peut fournir des indices supplémentaires sur l’origine de l’erreur.

5. Nettoyer et recompiler

Des fichiers compilés obsolètes peuvent parfois causer des problèmes. Essayez de nettoyer votre projet avec mix clean et de le recompiler avec mix compile.

6. Vérifier les imports et les alias

Assurez-vous que tous les imports et alias dans votre module sont corrects et ne causent pas de conflits ou d’erreurs de compilation.

7. Simplifier le module

Temporairement, commentez les parties complexes du module pour voir si le problème vient de certaines sections spécifiques. Par exemple, commentez les fonctions qui utilisent Person et voyez si le module compile sans elles.

En suivant ces étapes, vous devriez être en mesure de diagnostiquer et de résoudre le problème lié à la compilation de votre module Person. Si le problème persiste, il peut être utile de consulter la documentation d’Elixir ou de demander de l’aide sur des forums ou des groupes communautaires d’Elixir.

Solution pour un module elixir avec structure et fonctions

La préconisation dans ce paragraphe fonctionne et permet de définir dans un même module à la fois la structure et les fonctions pour manipuler la structure.

Nous devons modifier l’appel au nom de la structure dans les fonctions du module.

Le code correcte qui compile sans erreur :

defmodule MyApp.Person do
  @moduledoc """
    Module pour représenter une personne avec des fonctions pour accéder à ses propriétés.
  """

  # Définition de la structure sans valeurs par défaut
  defstruct name: "John Doe", age: 30, email: "john.doe@example.com"

  # Fonction pour obtenir le nom de la personne
  def get_name(%__MODULE__{name: name}), do: name

  # Fonction pour obtenir l'âge de la personne
  def get_age(%__MODULE__{age: age}), do: age

  # Fonction pour obtenir l'email de la personne
  def get_email(%__MODULE__{email: email}), do: email
end

Nous avons remplacé le nom « %Person » utilisé dans la fonction par « %__MODULE__ ».

Pour un code plus lisible nous utilisons alias __MODULE__ en ligne 5 ci-dessous :

defmodule MyApp.Person do
  @moduledoc """
  Module pour représenter une personne avec des fonctions pour accéder à ses propriétés.
  """
  alias __MODULE__

  defstruct [:name, :age, :email]

  def get_name(%Person{name: name}), do: name
  def get_age(%Person{age: age}), do: age
  def get_email(%Person{email: email}), do: email
end

Conclusion pour des modules avec une structure et des fonctions

Nous pouvons regrouper dans un même module des structures et des fonctions. Les fonctions du module ne peuvent pas utiliser le nom du module en cours de définition. Il faut utiliser « __MODULE__ » à la place. Le mieux est d’utiliser « alias __MODULE__ » pour un code plus lisible qui permet de retrouver le nom du module en cours de définition.

La solution présentée ici complète un précédent article montrant comment installer et débogguer du code Elixir dans VS Code.

Si vous avez aimé l'article vous êtes libre de le partager :-)

Laisser un commentaire