13. Listas

Vamos a repasar como se trabajan con las listas y profundizar con las funciones de Orden Superior.

Para entender como acceder a los elementos de una lista, vuelve a la lección de funciones y revisa las funciones car, cdr, first, second, rest, etc.

Para crear una lista, puedes usar la función list o la notación de comillas:

* (list 1 2 3)
(1 2 3)

(A B C)
* (list 'a 'b 'c)
(A B C)

* (list "Hola" "Mundo")
("Hola" "Mundo")
* '(1 2 3)
(1 2 3)

* '(A B C)
(A B C)

* '("Hola" "Mundo")
("Hola" "Mundo")

Ahora vamos a trabajar con funciones de orden superior diseñadas para operar sobre secuencias (listas, vectores, etc.).

Una función de orden superior es aquella que puede tomar otras funciones como argumentos o devolver funciones como resultado. No modifican la secuencia original, sino que devuelven una nueva secuencia con los resultados. Son fundamentales en la programación funcional y permiten manipular colecciones de datos de manera más declarativa.

Filtrado

Filtrar elementos implica seleccionar solo aquellos que cumplen con una condición específica, definida por una condición.

remove-if/ remove-if-not

Filtra elementos de una secuencia según un predicado.

;; Elimina los elementos pares
* (remove-if #'evenp '(1 2 3 4 5 6))
(1 3 5)

find-if / find-if-not

Devuelve el primer elemento que cumple (o no cumple) con una condición. Devolverá la misma cantidad, o menos, de la secuencia original.

* (find-if #'evenp '(1 2 3 4 5 6))
2

* (find-if-not #'evenp '(1 2 3 4 5 6))
1

Mapeo

Te permite transformar cada elemento de una secuencia aplicando una función a cada uno de ellos. En otros lenguajes siempre te darán la misma cantidad de elementos que la secuencia original, en Common Lisp depende de la función que apliques.

mapcar

Aplica una función a cada elemento de una secuencia y devuelve una nueva lista con los resultados.

;; Eleva al cuadrado cada número
* (mapcar 'list (lambda (x) (* x x)) '(1 2 3 4 5))
(1 4 9 16 25)

mapcan

Aplica una función a cada elemento de una secuencia y concatena los resultados en una sola lista. Devolverá una lista de igual longitud o superior.

;; Para cada número, devuelve una lista con el número y su cuadrado
* (mapcan (lambda (x) (list x (* x x))) '(1 2 3))
(1 1 2 4 3 9)

Es una función interesante porque filtra y transforma, como si usaras a la vez un remove-if y un mapcar en un solo paso. Por ejemplo, la podría utilizar para aplanar una lista.

* (mapcan (lambda (x) (if (listp x) x (list x))) '(1 (2 3) (4 5) 6))
(1 2 3 4 5 6)

Para ampliar una lista.

* (mapcan (lambda (x) (list x "-")) '("Hello" "World"))
("Hello" "-" "World" "-")

O tanto filtrar como transformar a la vez.

* (mapcan (lambda (word) (when word (list (format nil "~a~a" "#" word)))) '("lisp" "clojure" nil "racket" nil))
("#lisp" "#clojure" "#racket")

maplist

Es una función peculiar. En lugar de recorrer cada elemento de la lista, recibes la lista completa en cada iteración pero con un elemento menos cada vez. Se elimina el primer elemento, hasta que la lista queda vacía.

* (maplist #'(lambda (x) x) '('a 'b 'c 'd 'e))
(('A 'B 'C 'D 'E) ('B 'C 'D 'E) ('C 'D 'E) ('D 'E) ('E))

* (maplist #'(lambda (x) (length x)) '('a 'b 'c 'd 'e))
(5 4 3 2 1)

Lo puedes utilizar para asuntos de ordenación, comparación de listas, o para generar combinaciones de elementos donde necesites "mirar hacia adelante" en la lista (por ejemplo, para comparar cada elemento con el siguiente).

Reducción

reduce

Combina los elementos de una lista en un solo valor.

Por ejemplo, para sumar todos los números de una lista:

(reduce #'+ '(1 2 3 4))

O siendo más explícito:

* (reduce #'(lambda (accumulator item)
    (+ accumulator item)) '(1 2 3 4 5) :initial-value 0)
15
  • accumulator es el valor acumulado hasta el momento.
  • item es el elemento actual de la lista que se está procesando.
  • :initial-value es el valor inicial del acumulador. En este caso, comenzamos con 0 para la suma.

Predicados sobre secuencias

every

  • some
  • notary/notevery

Ordenamiento

  • sort
  • stable-sort

Aplicación

  • funcall
  • apply

Otras funciones útiles

position-if

count-if

member-if

Las que posiblemente usarás en tu día a día serán reduce, mapcar, remove-if y sort.

This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.

Desafíos de programación atemporales y multiparadigmáticos

Desafíos de programación atemporales y multiparadigmáticos

Te encuentras ante un librillo de actividades, divididas en 2 niveles de dificultad. Te enfrentarás a los casos más comunes que te puedes encontrar en pruebas técnicas o aprender conceptos elementales de programación.

Buy the book

Will you buy me a coffee?

Comments

There are no comments yet.

Visitors in real time

You are alone: 🐱