La expresión Elisp mapconcat
: ejemplos de uso y un caso práctico
La expresión mapconcat
aplica una función determinada sobre todos y cada uno de los elementos de una lista, y nos
devuelve el resultado como una cadena de texto. El primer argumento de mapconcat
es la función que queremos aplicar;
el segundo, la lista sobre la que vamos a aplicarla; el tercero, el separador que han de tener los elementos de la lista
cuando pasen a ser cadena de texto.
El escenario más básico de uso es cuando queremos, simplemente, convertir una lista en cadena de texto. Para ello, nos
bastaría con emplear una función que devolviese el argumento que toma (el elemento sobre el que se aplica) tal cual,
como identity
. Así, si tenemos la lista ("Fulano" "Mengano" "Zutano")
, podemos ensayar lo siguiente:
(message (mapconcat 'identity '("Fulano" "Mengano" "Zutano") " "))
mapconcat
aplica la función identity
sobre cada elemento de la lista y devuelve el propio elemento. Recordemos que
la lista ha de llevar un quote (un apóstrofe) para que no sea evaluado ninguno de sus elementos. El espaciador entre
elementos es un espacio simple. Todo eso se recoge en un mensaje al minibúfer. Si evaluamos la expresión, obtendremos:
"Fulano Mengano Zutano"
Otro ejemplo. Aquí la función a aplicar puede ser una simple función anónima (expresión lambda
) y el espaciador unos
puntos suspensivos seguidos de espacio simple:
(message (mapconcat (lambda (elemento) (format "Hola, %s" elemento)) '("Fulano" "Mengano" "Zutano") "... "))
Si evaluamos esto, obtendremos entonces como mensaje:
"Hola, Fulano... Hola, Mengano... Hola, Zutano"
Podemos complicarlo más, y hacer que la función anónima aplique una sustitución (la letra «o» reemplazada por «xxx»):
(message (mapconcat (lambda (elemento) (replace-regexp-in-string "o" "xxx" elemento)) '("Fulano" "Mengano" "Zutano") "... "))
Si lo evaluamos, obtenemos ahora:
"Fulanxxx... menganxxx... zutanxxx"
Un caso práctico
Queremos definir una función que nos haga lo siguiente:
- Toma los (nombres de) archivos marcados en el navegador de archivos Dired y hace una lista con ellos;
- esa lista pasa a cadena de texto, y
- la cadena de texto resultante se aplica como argumento de algún comando de
shell
.
Concretando más: queremos fusionar los archivos PDF que tengamos marcados en Dired en un único PDF, y para ello usaremos
el programa pdfjam
, incluido en TeX Live, de esta forma:
pdfjam archivo1.pdf archivo2.pdf archivo3.pdf -o archivo-resultante.pdf
Para conseguir eso, podemos ensayar esta función:
(defun fusiona-pdf () "fusiona en un único PDF varios PDF marcados en Dired, usando el programa pdfjam" (interactive) (let ((archivo (read-string "¿nombre del archivo de salida (sin extensión)?")) (pdf-lista (mapconcat 'identity (dired-get-marked-files) " "))) ;; esto convierte una lista en cadena de texto (shell-command (format "pdfjam %s -o %s.pdf" pdf-lista archivo))))
Nuestra función es muy simple, pero resultona. Consta de una expresión let
donde a la variable archivo
se asigna como
valor el nombre del PDF resultante, que debemos escribir (sin extensión) cuando se nos pregunte por ello. La variable
pdf-lista
toma la lista de archivos marcados en Dired (nuestros PDF a fusionar) y la pasa a cadena de texto de la
misma forma que vimos en nuestro primer ejemplo. La lista de PDF se obtiene con dired-get-marked-files
:
variable | valor |
---|---|
pdf-lista |
(mapconcat 'identity (dired-get-marked-files) " ") |
Y, finalmente, en el cuerpo de la expresión let
lanzamos el comando pdfjam
con las dos variables formadas según lo necesario.
∞
Publicado: 24/07/2019
Última actualización: 24/07/2019
Esta obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial 4.0 Internacional.