我注意到这个称为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中的函数是本地函数,因此您可以使用诸如recloopaux之类的通用名称作为它们的名称,并且它们不会污染代码的其他部分。

有一个类似的特殊运算符flet可以以相同的方式工作,但是它在本地环境中不包含自己的函数,因此您无法在其体内调用自己的函数。这些也很有用,但是您很少将它们称为rec,因为rec表示这是递归的。

这不是CL限制,而是编码样式。我确实在Scheme编程(另一个Lisp方言)中经常使用名称recloop,所以当我在CL中遇到它们时,我知道它们是什么,但是在CL中,从SO的答案中可以看出,我在全局变量中使用auxtest-aux称为test的函数。

10-06 05:41
查看更多