我注意到这个称为rec
的函数在Common Lisp代码中出现了很多次,但是我没有找到对其实际功能的引用。谁能告诉我这是什么吗?例如,它出现在另一个问题How to convert a flat list into a nested tree-like structure?的某些代码中:
(defun mimicry (source pattern)
(labels ((rec (pattern)
(mapcar (lambda (x)
(if (atom x)
(pop source)
(rec x)))
pattern)))
(rec pattern)))
最佳答案
除非您自己定义rec
,否则它不是代码中的全局函数。这是用labels
定义的本地辅助功能。
特殊运算符 labels
执行与defun
类似的任务,除了绑定(bind)是本地的。就像您使用defparameter
创建全局变量,并使用let
创建局部变量一样。
(labels ((banana (arg1) ; make function banana
(+ arg1 arg1)))
(banana 10)) ; use it
; banana doesn't exist anymore
是相同的:
(defun banan (arg1) ; make function banana
(+ arg1 arg1))
(banana 10) ; use it
; banana still exists
区别在于,香蕉不再存在于
labels
的外部,而使用defun
则在辅助功能的作用下侵害了全局环境。由于labels
中的函数是本地函数,因此您可以使用诸如rec
,loop
和aux
之类的通用名称作为它们的名称,并且它们不会污染代码的其他部分。有一个类似的特殊运算符
flet
可以以相同的方式工作,但是它在本地环境中不包含自己的函数,因此您无法在其体内调用自己的函数。这些也很有用,但是您很少将它们称为rec
,因为rec
表示这是递归的。这不是CL限制,而是编码样式。我确实在Scheme编程(另一个Lisp方言)中经常使用名称
rec
和loop
,所以当我在CL中遇到它们时,我知道它们是什么,但是在CL中,从SO的答案中可以看出,我在全局变量中使用aux
或test-aux
称为test
的函数。