Come applicare mapcar a una funzione con più argomenti


8

Ho packagesvariabili che hanno un elenco di utenti github e nomi di pacchetti.

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

Voglio git clonese il file non esiste ancora.

(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)))))

E voglio applicare git-clonea tutti i pacchetti variabili da packageselencare. Ma non sono riuscito a capire come applicare con argomenti.

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

2
A proposito, hai un extra 'nella tua defvardichiarazione.
Dan

1
FWIW, questo deve essere un duplicato, ma non ho tempo di cercarlo. ;-)
Drew

Risposte:


9

Puoi creare una funzione lambda anonima per prendere ogni elemento del tuo elenco e applicare la tua funzione ad esso.

Esempio:

(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)

Nota che, se non ti interessano i valori di ritorno (ad esempio, la tua funzione è solo per gli effetti collaterali, che qui sembra essere il caso), puoi usare mapcal posto di mapcar:

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

Per i tuoi scopi specifici, un ciclo può essere più semplice:

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

Non c'è alcun vantaggio per cl-dolistla pianura dolistqui.
npostavs,

@npostavs: modificato.
Dan

Grazie! Me ne sono completamente dimenticato funcall.
Feronsand

3
Hmm, ho saltato il funcallprima, ma guardando di nuovo sembra ridondante, perché non chiamare semplicemente toy-fnx?
npostavs,

@npostavs: corretto. Era solo un modo per illustrare mapcar e amici.
Dan

9

Se sei contento di usare dash.el puoi usare -eache destrutturare -let:

(require 'dash)

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

In alternativa, puoi utilizzare -lambdada dash.el per creare una funzione anonima con destrutturazione:

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

1

Partendo dalla risposta di Dan , se fai questo genere di cose spesso può essere utile definire una variante "stellata" di mapcar, come si fa in Python, ad esempio:

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

in modo che ad es

(my-mapcar* #'+ '((1) (1 1) (1 1 1) (1 1 1 1))
      ⇒ (1 2 3 4)  
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.