Cara menerapkan mapcar ke suatu fungsi dengan banyak argumen

8

Saya memiliki packagesvariabel yang memiliki daftar pengguna github dan nama paket.

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

Saya ingin git clonejika file tersebut belum ada.

(defun git-clone (author name)
  (let* ((repo-url (concat "[email protected]:" 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)))))

Dan saya ingin menerapkan git-clonesemua paket variabel ke packagesdaftar. Tetapi saya tidak tahu bagaimana cara mengajukan argumen.

; This obviously doesn't work
(mapcar `git-clone `packages)
pasir besi
sumber
2
Omong-omong, Anda memiliki tambahan 'dalam defvardeklarasi Anda .
Dan
1
FWIW, ini harus menjadi duplikat, tapi saya tidak punya waktu untuk mencarinya. ;-)
Drew

Jawaban:

9

Anda dapat membuat fungsi lambda anonim untuk mengambil setiap elemen dari daftar Anda dan menerapkan fungsi Anda ke dalamnya.

Contoh:

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

Perhatikan bahwa, jika Anda tidak peduli dengan nilai pengembalian (yaitu, fungsi Anda hanya untuk efek samping, yang tampaknya merupakan kasus di sini), Anda dapat menggunakannya mapcsebagai ganti mapcar:

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

Untuk tujuan spesifik Anda, satu loop mungkin paling sederhana:

(cl-dolist (package packages)      ; or dolist if you don't want to use cl-lib
  (funcall #'toy-fnx (car package) (cdr package)))
Dan
sumber
Tidak ada cl-dolistuntungnya di dolistsini.
npostavs
@npostavs: diedit.
Dan
Terima kasih! Saya benar-benar lupa funcall.
ironsand
3
Hmm, saya melewatkan funcallsebelumnya, tetapi melihat lagi sepertinya berlebihan, mengapa tidak toy-fnxlangsung menelepon ?
npostavs
@npostavs: benar. Itu hanya cara untuk menggambarkan mapcar dan teman-teman.
Dan
9

Jika Anda senang menggunakan dash.el, Anda dapat menggunakan -eachdan merusak -let:

(require 'dash)

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

Atau, Anda dapat menggunakan -lambdadari dash.el untuk membuat fungsi anonim dengan merusak:

(mapcar
 (-lambda ((author . name)) (git-clone author name))
 packages)
Wilfred Hughes
sumber
1

Membangun berdasarkan jawaban oleh Dan , jika Anda sering melakukan hal semacam ini, mungkin berguna untuk mendefinisikan varian 'yang berkilau bintangnya' mapcar, seperti yang dilakukan dalam contoh Python:

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

sehingga mis

(my-mapcar* #'+ '((1) (1 1) (1 1 1) (1 1 1 1))
      ⇒ (1 2 3 4)  
Abel Stern
sumber