在常见的lisp中,我可以这样做:
(mapcar #'cons '(1 2 3) '(a b c))
=> ((1 . A) (2 . B) (3 . C))
Run Code Online (Sandbox Code Playgroud)
我如何在elisp中做同样的事情?当我尝试时,我收到一个错误:
(wrong-number-of-arguments mapcar 3)
Run Code Online (Sandbox Code Playgroud)
如果elisp的mapcar一次只能在一个列表上工作,那么将两个列表组合成一个列表的自动方式是什么?
Jon*_*rdy 19
你想要的mapcar*,它接受一个或多个序列(不仅仅是Common Lisp中的列表),并且对于一个序列参数就像常规一样工作mapcar.
(mapcar* #'cons '(1 2 3) '(a b c))
((1 . A) (2 . B) (3 . C))
Run Code Online (Sandbox Code Playgroud)
即使没有定义,你也可以轻松推出自己的:
(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)))))
Run Code Online (Sandbox Code Playgroud)
Mir*_*lov 10
Emacs内置了Common Lisp库,它引入了大量Common Lisp函数和宏,但带有cl-前缀.没有理由避免使用此库.cl-mapcar是你想要的:
(cl-mapcar '+ '(1 2 3) '(10 20 30)) ; (11 22 33)
Run Code Online (Sandbox Code Playgroud)
使用dash列表操作库(请参阅安装说明),您可以使用-zip-with(记住:-zip-with与cl-mapcar应用于2个列表相同):
(-zip-with '+ '(1 2 3) '(10 20 30)) ; (11 22 33)
Run Code Online (Sandbox Code Playgroud)
我不知道实现-zip-with3个参数的等价物的优雅方式.但是,你可以使用-partial从dash-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)
Run Code Online (Sandbox Code Playgroud)
然后,您可以将它与-reduce函数一起使用:
(-reduce (-partial '-zip-with '+) '((1 2 3) (10 20 30) (100 200 300)))
; (111 222 333)
Run Code Online (Sandbox Code Playgroud)
您可以使用&rest关键字将其包装到函数中,因此此函数将接受不同数量的参数而不是列表:
(defun -map* (&rest lists)
(-reduce (-partial 'zip-with '+) lists))
Run Code Online (Sandbox Code Playgroud)