複数の引数を持つ関数にmapcarを適用する方法


8

packagesgithubユーザーとパッケージ名のリストを持つ変数があります。

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

git cloneファイルがまだ存在しない場合、私はしたいです。

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

リストgit-cloneするすべてのパッケージ変数に適用したいと思いますpackages。しかし、私は議論を適用する方法を理解することができませんでした。

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

2
ちなみに、あなたは'あなたのdefvar宣言に追加があります。
ダン

1
FWIW、これは重複している必要がありますが、検索する時間はありません。;-)
ドリュー

回答:


9

匿名のラムダ関数を作成して、リストの各要素を取得し、それに関数を適用できます。

例:

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

戻り値を気にしない場合(つまり、関数が副作用のみであり、ここではそうであるように見える場合)、のmapc代わりに使用できますmapcar

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

あなたの特定の目的のために、ループは最も簡単かもしれません:

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

ここcl-dolistで平文を超える利点はありませんdolist
npostavs

@npostavs:編集。
ダン

ありがとう!完全に忘れていましたfuncall
鉄砂2015

3
うーん、funcall以前はスキップしましたが、もう一度見ると冗長に見えますtoy-fnx。直接呼び出すだけではどうですか。
npostavs 2015

@npostavs:正解です。これは、mapcarと友人を説明するための単なる方法でした。
ダン

9

あなたがいる幸せ使用している場合dash.elを、あなたは使用することができます-eachし、構造化代入します-let

(require 'dash)

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

または、-lambdadash.elから使用して、構造化を解除して無名関数を作成することもできます。

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

1

Dan回答に基づいて、この種のことを頻繁に行う場合mapcar、Pythonのように、の「スター付き」バリアントを定義すると便利な場合があります。

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

それで例えば

(my-mapcar* #'+ '((1) (1 1) (1 1 1) (1 1 1 1))
      ⇒ (1 2 3 4)  
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.