Funciones de alto orden en Elixir

En Elixir, como en muchos lenguajes de programación funcionales, en vez de tener un montón de funciones especializadas en un montón de tipos de datos diversos, tenemos funciones generales de alto orden que aceptan como parámetro más funciones, con las cuales podemos especificar cómo queremos que funcionen.

Los lenguajes de programación funcionales, aunque cada uno se presenta como único, comparten características fundamentales que los hacen muy similares cuando los analizamos en profundidad. Uno de esos conceptos clave es el de las funciones de primera clase. En Elixir, esto significa que las funciones no son solo bloques de código aislados, sino que podemos tratarlas como cualquier otro dato: podemos asignarlas a variables, pasarlas como argumentos a otras funciones o devolverlas como resultados.

Por ejemplo, si tenemos una función como String.upcase/1, que transforma una cadena a mayúsculas, podemos capturarla usando el operador ampersand y asignarla a un identificador. Así, podemos hacer algo como:

mayusculas = &String.upcase/1
mayusculas.("hola") # Devuelve "HOLA"

Además, podemos definir funciones anónimas fácilmente. Por ejemplo, una función que duplique un número se puede escribir así:

doble = fn x -> x * 2 end
doble.(5) # Devuelve 10

Este manejo flexible de funciones nos lleva al siguiente concepto fundamental: las funciones de alto orden. Estas son funciones que reciben otras funciones como parámetros o que devuelven funciones. En Elixir, un ejemplo sencillo es la función apply/2, que nos permite aplicar una función a una lista de argumentos. Por ejemplo, si queremos aplicar la función doble a un valor, podemos hacerlo de dos maneras:

doble.(5) # Forma directa, devuelve 10

apply(doble, [5]) # Forma usando apply, también devuelve 10

La función apply es muy general y puede recibir funciones con diferentes números de parámetros, siempre que la lista de argumentos coincida con la aridad de la función. Por ejemplo, si capturamos la función rem/2 (que calcula el resto de una división), podemos usar apply para pasarle dos argumentos:

apply(&rem/2, [9, 2]) # Devuelve 1

Aunque apply es una función de alto orden muy versátil, en la práctica usamos otras funciones de alto orden que están diseñadas para trabajar con colecciones de datos, como listas, tuplas o mapas. En Elixir, estas funciones se encuentran en el módulo Enum y son herramientas esenciales para el día a día.

Entre ellas, map nos permite transformar cada elemento de una colección aplicándole una función. Por ejemplo, si queremos duplicar cada número de una lista, haríamos:

Enum.map([1, 2, 3], fn x -> x * 2 end) # Devuelve [2, 4, 6]

La función filter nos ayuda a seleccionar solo aquellos elementos que cumplen una condición. Por ejemplo, para quedarnos con los números pares de una lista:

Enum.filter([1, 2, 3, 4], fn x -> rem(x, 2) == 0 end) # Devuelve [2, 4]

Por último, reduce nos permite combinar todos los elementos de una colección en un único valor, aplicando una función acumulativa. Por ejemplo, para sumar todos los números de una lista:

Enum.reduce([1, 2, 3, 4], 0, fn x, acc -> x + acc end) # Devuelve 10

Estas funciones no son exclusivas de Elixir; muchos lenguajes funcionales y algunos imperativos también las incluyen, lo que facilita trabajar con colecciones de manera declarativa y elegante. Así, al dominar las funciones de primera clase y las funciones de alto orden, podemos escribir código más flexible, reutilizable y expresivo en Elixir.

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