1

假设我们有一个如下列表:

("These" "Are "Some" "Words"), 让我们称之为listy

如何在列表的每个项目上调用一个函数?

也许调用一个函数,如:

(defun messager (somelist) 
 (interactive)
 (message somelist)
)

运行函数:

(messager listy)

我希望在缓冲区中看到列表中每个项目的单独行。

但是,不起作用的部分是循环或遍历列表中的项目。

4

2 回答 2

7

利用

(mapc 'messager listy)

或者

(dolist (item listy)
  (messager item))
于 2013-01-11T21:18:56.623 回答
0

现在,我将再次进行自我广告: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: 高阶函数与现有函数很好地结合。因此,如果您已经有一个想要应用于每个元素的元素 - 这可能是解决问题的最佳方法。但是,如果您要创建一个函数只是为了将它与高阶函数一起使用 - 那么它很少有回报,因为您将创建一个“冗余”实例,否则您可以避免这种情况。并非总是如此,有时,尤其是与宏一起使用时,这可能是一个强大的工具,但就像您的情况一样,迭代似乎更适合。

于 2013-01-11T23:05:37.090 回答