映射的elisp

问题描述:

Common Lisp中了两个列表的功能,我可以做到这一点:映射的elisp

(mapcar #'cons '(1 2 3) '(a b c)) 

=> ((1 . A) (2 . B) (3 . C)) 

我该怎么做同样的事情在elisp的?当我尝试,我得到一个错误:

(wrong-number-of-arguments mapcar 3) 

如果elisp的的mapcar可以在一个名单上每次只工作,怎么是两个清单合并成一个ALIST的idomatic方式?

你想mapcar*,它接受一个或多个序列(不只是列出了在Common Lisp的),以及一个序列参数工作就像普通mapcar

(mapcar* #'cons '(1 2 3) '(a b c)) 
((1 . A) (2 . B) (3 . C)) 

即使没有定义它,你可以很容易滚你自己:

(defun mapcar* (f &rest xs) 
    "MAPCAR for multiple sequences" 
    (if (not (memq nil xs)) 
    (cons (apply f (mapcar 'car xs)) 
     (apply 'mapcar* f (mapcar 'cdr xs))))) 

Emacs中内置了Common Lisp library,它引入了大量的Common Lisp的函数和宏,但与前缀为cl-。没有理由避免这个库。 cl-mapcar是你想要什么:

(cl-mapcar '+ '(1 2 3) '(10 20 30)) ; (11 22 33) 

随着dash列表操作库(见installation instructions),你可以使用-zip-with(记住:-zip-withcl-mapcar同样适用于2所列出):

(-zip-with '+ '(1 2 3) '(10 20 30)) ; (11 22 33) 

我不知道为3个参数实现等效的-zip-with的优雅方式。但是,你可以使用-partialdash-functional包,自带dash(功能从dash-functional需要Emacs的24)。 -partial部分应用功能,所以下面这两个函数调用是等效的:

(-zip-with '+ '(1 2) '(10 20)) ; (11 22) 
(funcall (-partial '-zip-with '+) '(1 2) '(10 20)) ; (11 22) 

然后,你可以用它与-reduce功能:

(-reduce (-partial '-zip-with '+) '((1 2 3) (10 20 30) (100 200 300))) 
; (111 222 333) 

您可以&rest关键字把它包装成一个函数,所以这个函数会接受不同数量的参数而不是一个列表:

(defun -map* (&rest lists) 
    (-reduce (-partial 'zip-with '+) lists))