关于闭包:在 Lisp 中如何调用函数列表中的函数?

 2022-01-07 

How do you call functions in a list of functions in Lisp?

我正在阅读实用的 Common Lisp,并且我正在玩 REPL 中的闭包(第 6 章)。我正在尝试以下代码,我认为它列出了一个闭包列表,但我无法弄清楚如何在 REPL 中同时调用所有这些代码:

1
2
3
4
5
6
(defparameter *fn*
   (let ((count 10))
     (list
      #'(lambda () (incf count))
      #'(lambda () (decf count))
      #'(lambda () count))))

我已经阅读了这个问题的答案并尝试了一些和其他一些,但似乎没有任何效果。这是我尝试过的 --

1
2
3
4
5
6
7
8
9
CL-USER> (apply #'funcall *fn*)
; Evaluation aborted on #<CCL::TOO-MANY-ARGUMENTS #x2100B8890D>.
CL-USER> (funcall *fn*)
; Evaluation aborted on #<TYPE-ERROR #x2100B5667D>.
CL-USER> (loop for function in *fn*
      (collect (funcall function)))
; Evaluation aborted on #<CCL::SIMPLE-PROGRAM-ERROR #x2100C21D4D>.
CL-USER> (map #'funcall *fn*)
; Evaluation aborted on #<CCL::TOO-FEW-ARGUMENTS #x2100B7320D>.

我正在寻找的是可以打印的东西 (11 9 10)。

感谢您的帮助!


您可以使用 mapcar 代替 map:

1
2
CL-USER> (mapcar #'funcall *fn*)
(11 10 10)

但是,您会注意到这会打印 (11 10 10) 而不是 (11 9 10)。这是因为 count*fn* 中的 lambdas 之间共享,因为 let 范围将它们都包含在内。

如果您希望 count 绑定到每个 lambda 中的不同变量,您必须为每个 lambda 构建一个不同的 let 作用域。


1
2
3
4
5
6
7
(funcall (first *fn*))

(loop for f in *fn* collect (funcall f))

(map 'list #'funcall *fn*)

(mapcar #'funcall *fn*)