Cómo aplicar mapcar a una función con múltiples argumentos


8

Tengo packagesvariables que tienen una lista de usuarios de github y nombres de paquetes.

(defvar packages '('("auto-complete" . "auto-complete")
                   ("defunkt" . "markdown-mode")))

Quiero git clonesi el archivo aún no existe.

(defun git-clone (author name)
  (let* ((repo-url (concat "git@github.com:" author "/" name ".git")))
    (print repo-url)
    (unless (file-exists-p (concat "~/.emacs.d/git/" name))
      (shell-command (concat "git clone " repo-url " ~/.emacs.d/git/" name)))))

Y quiero aplicar git-clonea todos los paquetes variables a la packageslista. Pero no pude entender cómo aplicar con argumentos.

; This obviously doesn't work
(mapcar `git-clone `packages)

2
Por cierto, tienes un extra 'en tu defvardeclaración.
Dan

1
FWIW, esto tiene que ser un duplicado, pero no tengo tiempo para buscarlo. ;-)
Drew

Respuestas:


9

Puede crear una función lambda anónima para tomar cada elemento de su lista y aplicarle su función.

Ejemplo:

(defvar packages '(("auto-complete" . "auto-complete")
                   ("defunkt" . "markdown-mode")))

(defun toy-fnx (author name)
  "Just testing."
  (message "Package %s by author %s" name author)
  (sit-for 1))

(mapcar (lambda (package)
          (funcall #'toy-fnx (car package) (cdr package)))
        packages)

Tenga en cuenta que, si no le importan los valores de retorno (es decir, su función es solo para efectos secundarios, que parece ser el caso aquí), puede usar mapcen lugar de mapcar:

(mapc (lambda (package)
        (funcall #'toy-fnx (car package) (cdr package)))
      packages)

Para sus propósitos específicos, un bucle puede ser más simple:

(cl-dolist (package packages)      ; or dolist if you don't want to use cl-lib
  (funcall #'toy-fnx (car package) (cdr package)))

No hay ninguna ventaja cl-dolistsobre el llano dolistaquí.
npostavs

@npostavs: editado.
Dan

¡Gracias! Me olvidé por completo funcall.
ironsand

3
Hmm, salté el funcallanterior, pero mirando de nuevo parece redundante, ¿por qué no llamar toy-fnxdirectamente?
npostavs

@npostavs: correcto. Era solo una forma de ilustrar mapcar y amigos.
Dan

9

Si está satisfecho con dash.el , puede usar -eachy desestructurar -let:

(require 'dash)

(--each packages
  (-let [(author . name) it]
    (git-clone author name)))

Alternativamente, puede usar -lambdadesde dash.el para crear una función anónima con desestructuración:

(mapcar
 (-lambda ((author . name)) (git-clone author name))
 packages)

1

Sobre la base de la respuesta de Dan , si haces este tipo de cosas con frecuencia, puede ser útil definir una variante 'destacada' de mapcar, como se hace, por ejemplo, en Python:

(defun my-mapcar* (func arglist)
  (mapcar 
     (lambda (args)
       (apply func args))
     arglist))

para que, por ejemplo

(my-mapcar* #'+ '((1) (1 1) (1 1 1) (1 1 1 1))
      ⇒ (1 2 3 4)  
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.