假设我们有一个如下列表:
("These" "Are "Some" "Words")
, 让我们称之为listy
如何在列表的每个项目上调用一个函数?
也许调用一个函数,如:
(defun messager (somelist)
(interactive)
(message somelist)
)
运行函数:
(messager listy)
我希望在缓冲区中看到列表中每个项目的单独行。
但是,不起作用的部分是循环或遍历列表中的项目。
利用
(mapc 'messager listy)
或者
(dolist (item listy)
(messager item))
现在,我将再次进行自我广告:P 但希望我能在途中传达一些有用的信息:
;; Here is what `dolist' expands to:
(dolist (item listy)
(messager item))
(identity
(catch (quote --cl-block-nil--)
(let ((--dolist-tail-- listy) item)
(while --dolist-tail--
(setq item (car --dolist-tail--))
(messager item)
(setq --dolist-tail-- (cdr --dolist-tail--))))))
;; And here is what `i-iterate' expands to:
(++ (for item in listy)
(messager item))
(let* ((--0 listy) item)
(while --0
(setq item (car --0) --0 (cdr --0))
(messager item)))
一些评论:无论是否存在条件退出,dolist
都会创建一个块,而只有在确定了这样的条件退出时才会尝试这样做。通常,在表单中执行代码会慢一些。(catch ...)
i-iterate
(catch ...)
此外,dolist
会将代码包装到一个特殊的“块”中(这基本上只是对identity
函数的调用。这也是一种杂乱无章的东西,这是默认设置,但并不总是需要。
现在,对于关于 的其他问题alist
,您可以像这样使用loop
宏:
(loop for (key . value) in '((a . b) (c . d)) do
(message "key: %s -> value: %s" key value))
;; Which expands to:
(identity
(catch (quote --cl-block-nil--)
(let* ((--cl-var-- (quote ((a . b) (c . d)))) (value nil) (key nil))
(while (consp --cl-var--)
(setq value (car --cl-var--)
key (car (prog1 value (setq value (cdr value)))))
(message "key: %s -> value: %s" key value)
(setq --cl-var-- (cdr --cl-var--))) nil)))
;; Compared to i-iterate
(++ (for (key . value) in '((a . b) (c . d)))
(message "key: %s -> value: %s" key value))
;; Which expands to:
(let* ((--0 (quote ((a . b) (c . d)))) value key)
(while --0
(setq key (caar --0) value (cdar --0) --0 (cdr --0))
(message "key: %s -> value: %s" key value)))
在这种特殊情况下,使用pop
是不合理的。同样使用(catch ...)
块(因为没有条件退出)。
哦,还有图书馆的链接:http ://code.google.com/p/i-iterate/ :)
用于此目的的优点和缺点mapc
: 高阶函数与现有函数很好地结合。因此,如果您已经有一个想要应用于每个元素的元素 - 这可能是解决问题的最佳方法。但是,如果您要创建一个函数只是为了将它与高阶函数一起使用 - 那么它很少有回报,因为您将创建一个“冗余”实例,否则您可以避免这种情况。并非总是如此,有时,尤其是与宏一起使用时,这可能是一个强大的工具,但就像您的情况一样,迭代似乎更适合。