9

I have packages variables that have list of github users and package names.

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

I want to git clone if the file is not exist yet.

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

And I want to apply git-clone to all packages variable to packages list. But I could not figure out how to apply with arguments.

; This obviously doesn't work
(mapcar `git-clone `packages)
Drew
  • 75,699
  • 9
  • 109
  • 225
ironsand
  • 403
  • 3
  • 14

3 Answers3

9

You can create an anonymous lambda function to take each element of your list and apply your function to it.

Example:

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

Note that, if you don't care about the return values (ie, your function is only for side effects, which appears to be the case here), you can use mapc in place of mapcar:

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

For your specific purposes, a loop may be simplest:

(cl-dolist (package packages)      ; or dolist if you don't want to use cl-lib
  (funcall #'toy-fnx (car package) (cdr package)))
Dan
  • 32,584
  • 6
  • 98
  • 168
9

If you're happy using dash.el you can use -each and destructuring -let:

(require 'dash)

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

Alternatively, you can use -lambda from dash.el to create an anonymous function with destructuring:

(mapcar
 (-lambda ((author . name)) (git-clone author name))
 packages)
Wilfred Hughes
  • 6,890
  • 2
  • 29
  • 59
1

Building on the answer by Dan, if you do this kind of thing often it may be useful to define a 'starred' variant of mapcar, as one does in e.g. Python:

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

so that e.g.

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