我想映射列表,但要跟踪列表中的元素索引.
在Python中,我可以做一些事情:
map(lambda (idx, elt): "Elt {0}: {1}".format(idx, elt), enumerate(mylist))
Run Code Online (Sandbox Code Playgroud)
我试图将其翻译成以下内容:
(mapcar-something (lambda (elt idx) (format nil "Elt ~D: ~S" idx elt))
'(a b c d))
Run Code Online (Sandbox Code Playgroud)
预期结果:
("Elt 0: A" "Elt 1: B" "Elt 2: C" "Elt 3: D")
Run Code Online (Sandbox Code Playgroud)
但我找不到我应该使用的mapcar-something功能.我是否需要自己实现(通过循环,也许)?
CL-USER 25 > (defun iota (n)
(loop for i below n collect i))
IOTA
CL-USER 26 > (iota 4)
(0 1 2 3)
CL-USER 27 > (mapcar (lambda (elt idx)
(format nil "Elt ~D: ~S" idx elt))
'(a b c d)
(iota 4))
("Elt 0: A" "Elt 1: B" "Elt 2: C" "Elt 3: D")
Run Code Online (Sandbox Code Playgroud)
要么
CL-USER 28 > (loop for elt in '(a b c d) and idx from 0
collect (format nil "Elt ~D: ~S" idx elt))
("Elt 0: A" "Elt 1: B" "Elt 2: C" "Elt 3: D")
Run Code Online (Sandbox Code Playgroud)
Common Lisp 的 LOOP 宏可以自动跟踪索引。
(loop for elt in '(a b c d) and idx from 0
collect (operation-on idx elt))
Run Code Online (Sandbox Code Playgroud)
LOOP 自动将用;初始化的变量加1 from
如果它们被引入,and
那么两个赋值(数组的元素和索引)都会立即发生,而不是嵌套。
因此,枚举函数将类似于:
(defun enumerate (list &optional (first-index 0))
(loop for elt in list and idx from first-index
collect (cons idx elt)))
Run Code Online (Sandbox Code Playgroud)
在 Common Lisp 的表达能力中,按照以下方式定义宏可能会很有用:
(defmacro with-enumerated-list ((list elt idx &key (first-index 0)) &body body)
`(loop for ,elt in ,list and ,idx from ,first-index
collect (progn ,@body)))
Run Code Online (Sandbox Code Playgroud)
在这种情况下,枚举函数可以简化为:
(defun enumerate (list &optional (first-index 0))
(with-enumerated-list (list elt idx :first-index first-index)
(cons idx elt)))
Run Code Online (Sandbox Code Playgroud)