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

时间:2014-10-05 19:37:35

标签: common-lisp

我注意到这个名为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)))

1 个答案:

答案 0 :(得分:9)

rec不是代码中的全局函数,除非您自己定义它。它是使用labels定义的本地辅助函数。

特殊运算符labels执行与defun类似的任务,但绑定是本地的。这就像您使用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编程中使用名称recloop(另一种Lisp方言),所以当我在CL中遇到它们时我知道它们是什么,但在CL中我从我的答案中看到了SO我在名为aux的全局函数中使用test-auxtest