在带有标签的Common Lisp源中调用rec的未记录函数?

dk1*_*123 5 common-lisp

我注意到这个函数rec在Common Lisp代码中多次出现,但是我没有找到它实际上在做什么的引用.任何人都可以向我解释它是什么?例如,它出现在另一个问题的一些代码中,如何将平面列表转换为嵌套的树状结构?:

(defun mimicry (source pattern)
  (labels ((rec (pattern)
             (mapcar (lambda (x)
                       (if (atom x)
                         (pop source)
                         (rec x)))
                     pattern)))
    (rec pattern)))
Run Code Online (Sandbox Code Playgroud)

Syl*_*ter 9

rec在您的代码中不是全局函数,除非您自己定义它.它是一个定义的本地辅助函数labels.

特殊操作员labels执行类似的任务,defun除了绑定是本地的.这就像你defparameter用来制作全局变量和let制作本地变量一样.

(labels ((banana (arg1)    ; make function banana
           (+ arg1 arg1)))
  (banana 10))             ; use it
; banana doesn't exist anymore
Run Code Online (Sandbox Code Playgroud)

是相同的:

(defun banan (arg1) ; make function banana
  (+ arg1 arg1))
(banana 10)         ; use it
; banana still exists
Run Code Online (Sandbox Code Playgroud)

不同之处在于香蕉不再存在于外面,labels使用defun辅助功能会侵蚀您的全球环境.由于功能labels是局部的,你可以像使用普通的名字rec,loopaux为他们的名字,他们不会污染代码的其他部分.

有一个类似的特殊运算符调用flet它以相同的方式工作,但它在本地环境中不包含它自己的函数,阻止你在它的体内调用你自己的函数.这些也很有用但你很少调用它们,rec因为rec暗示它是递归的东西.

这不是CL限制,而是编码风格.我确实使用这个名字rec,loop经常在Scheme编程中使用(另一个Lisp方言),所以当我在CL中遇到它们时我知道它们是什么,但在CL中我从我的答案中看到我使用auxtest-aux在一个名为的全局函数内部test.