Estructuras con defstruct

Con la palabra clave defstruct podemos crear estructuras. Son como mapas, pero tienen una semántica que declaramos nosotros y que es mucho más fija. Conviene tenerlo en mente si pretendemos usar librerías como Ecto (y por ende, por ejemplo, Phoenix).

Las estructuras en Elixir, conocidas como structs, son una forma de darle forma y semántica a los mapas, limitando las claves que pueden contener y facilitando su manejo. A diferencia de los mapas ordinarios, que pueden tener cualquier clave, los structs nos permiten definir un conjunto fijo de campos, lo que ayuda a evitar errores y a expresar mejor la intención de nuestros datos.

Para crear un struct, debemos definirlo dentro de un módulo usando la palabra clave defstruct. Por ejemplo, si queremos representar un perfil con campos como nombre, país, bebida, comida y animal, lo haríamos así:

defmodule Perfil do
  defstruct [:nombre, :país, :bebida, :comida, :animal]
end

Al crear una instancia de este struct, usamos la sintaxis %Perfil{}. Si lo creamos vacío, el struct tendrá todas las claves definidas con valor nil por defecto:

perfil = %Perfil{}
# %Perfil{nombre: nil, país: nil, bebida: nil, comida: nil, animal: nil}

Aunque los structs son mapas bajo el capó, tienen una clave oculta que indica su tipo, lo que permite que Elixir los distinga de mapas normales. Esto significa que podemos acceder a sus campos con la sintaxis de acceso a mapas, como perfil.animal o perfil[:bebida].

Sin embargo, a diferencia de los mapas, los structs no permiten añadir claves arbitrarias. Si intentamos agregar una clave que no está definida en el struct, como :hola, el resultado dejará de ser un struct válido y se convertirá en un mapa común, perdiendo la semántica que habíamos definido. Por ejemplo:

perfil = %Perfil{}
perfil_modificado = Map.put(perfil, :hola, "adiós")
# perfil_modificado ya no es un struct Perfil válido

Esto nos ayuda a mantener la integridad de nuestros datos y a evitar que se introduzcan claves inesperadas.

También podemos asignar valores por defecto a los campos del struct al definirlo. Para ello, en lugar de pasar solo una lista de átomos, pasamos una lista de pares clave-valor, como una keyword list:

defmodule Perfil do
  defstruct nombre: nil, país: nil, bebida: nil, comida: "papayons", animal: nil
end

Con esta definición, si no especificamos un valor para comida al crear el struct, automáticamente tendrá el valor "papayons".

Los structs permiten hacer pattern matching, tanto entre structs del mismo tipo como con mapas ordinarios, siempre que las claves coincidan. Sin embargo, no podemos hacer pattern matching directamente entre un mapa y un struct sin tener en cuenta la clave oculta que identifica el struct.

Un uso muy común de los structs en Elixir es en librerías como Ecto, que es un ORM para bases de datos. Ecto utiliza structs para representar filas de tablas, lo que permite definir claramente los campos que esperamos en cada registro y facilita la conversión entre datos de la base y estructuras en Elixir.

En definitiva, los structs son una herramienta sencilla pero poderosa para dar forma y significado a nuestros datos en Elixir, ayudándonos a evitar errores y a trabajar con información más estructurada y clara.

Lista de reproducción
  1. 1
    ¿Qué es Elixir?
    10 minutos
  2. 2
    Instalación de Elixir
    9 minutos
  3. 3
    ¿Qué es la programación funcional? (Como la de Elixir)
    20 minutos
  4. 4
    ¿Cómo funciona la REPL de Elixir?
    7 minutos
  5. 5
    ¿Cómo hacer asignaciones en Elixir?
    7 minutos
  6. 6
    Operadores aritméticos básicos
    6 minutos
  7. 7
    ¿Qué son los tipos de datos de Elixir?
    5 minutos
  8. 8
    Átomos en Elixir
    4 minutos
  9. 9
    Las palabras clave nil, true y false
    6 minutos
  10. 10
    Operadores lógicos de comparación
    8 minutos
  11. 11
    Comparación estricta con ===
    3 minutos
  12. 12
    Operadores lógicos y proposicionales
    8 minutos
  13. 13
    Invocación de funciones
    10 minutos
  14. 14
    Fundamentos de funciones
    9 minutos
  15. 15
    Cadenas de caracteres
    8 minutos
  16. 16
    Entrada y salida estandar de la mano de gets y puts
    9 minutos
  17. 17
    Concatenar e interpolar strings
    9 minutos
  18. 18
    Código fuente en archivos
    9 minutos
  19. 19
    Condicional IF y bloques DO-END
    11 minutos
  20. 20
    IFs anidados, UNLESS y COND
    12 minutos
  21. 21
    Definición de funciones
    11 minutos
  22. 22
    Fundamentos de compilación de módulos
    6 minutos
  23. 23
    Guardas
    8 minutos
  24. 24
    Funciones anónimas
    7 minutos
  25. 25
    Capturar funciones
    4 minutos
  26. 26
    Invocación de funciones dentro del mismo módulo
    7 minutos
  27. 27
    Tuplas
    8 minutos
  28. 28
    Introducción al pattern matching
    8 minutos
  29. 29
    Pattern matching en funciones
    11 minutos
  30. 30
    Las tuplas :ok, :error
    7 minutos
  31. 31
    case
    10 minutos
  32. 32
    Operador pin
    7 minutos
  33. 33
    Pattern matchings y recursividad
    5 minutos
  34. 34
    Listas
    9 minutos
  35. 35
    Operadores y funciones de lista
    10 minutos
  36. 36
    Keyword lists: listas de palabras clave
    8 minutos
  37. 37
    Mapas
    7 minutos
  38. 38
    Pattern matching de mapas y keyword lists
    6 minutos
  39. 39
    Operadores y funciones para mapas y keyword lists
    5 minutos
  40. 40
    Estructuras con defstruct
    11 minutos
  41. 41
    Bitstrings
    11 minutos
  42. 42
    Charlists
    10 minutos
  43. 43
    Funciones de alto orden en Elixir
    5 minutos
  44. 44
    Uso de la función filter
    10 minutos
  45. 45
    Uso de la función map
    7 minutos
  46. 46
    Uso de la función reduce
    9 minutos
  47. 47
    Pipelines
    11 minutos
  48. 48
    Rangos y Streams
    11 minutos
  49. 49
    Funciones recursivas con listas
    14 minutos