这个lisp示例是否具有尾递归功能?

时间:2013-11-13 11:52:29

标签: recursion lisp common-lisp tail-recursion

我的理解是尾递归是递归,其中返回值不是完成操作所必需的;也就是说,递归是函数的最后一步,一旦它进行递归调用,函数的其余部分就完成了。

对此,我问这个例子(来自Norvig先生)是否是尾递归:

(defparameter *titles*
  '(Mr Mrs Miss Ms Sir Madam Dr Admiral Major General)
  "A list of titles that can appear at the start of a name.")

(defun first-name (name)
  "Select the first name from a name represented as a list." 
  (if (member (first name) *titles*)
     (first-name (rest name))
     (first name)))

一旦最后的first-name被称为if语句的一个分支,那么该函数没有其他功能;因此,它是尾递归?

2 个答案:

答案 0 :(得分:2)

是的,这是一个例子。

尾部递归优化在Common Lisp的许多实现中都可用,但规范并不要求它。 这意味着您可以使用Common Lisp而无需尾递归优化。

您可能还会发现您正在使用的版本需要稍微调整才能执行此优化。

因此在某些实现中,您可能需要使用'declare'来通知编译器您希望优化速度。

(defun first-name (name)
  "Select the first name from a name represented as a list." 
  (declare (optimize (speed 3) (compilation-speed 0) (debug 0) (safety 1)))
  (if (member (first name) *titles*)
      (first-name (rest name)) 
      (first name)))

修改 This site现在已有几年了,但可能会提供一些信息。

当Joshua和Rainer在这里大量改进细节时,请务必阅读评论。

答案 1 :(得分:2)

是和否。通常是的。如果编译器支持TCO并且正确的优化设置处于活动状态,它也将进行优化。 但有时编译器无法对其进行优化。

如果name被宣布为特殊,那么可能不会。

如果有类似

的话
(defvar name '(susanne mustermann))

然后函数的参数name将被声明为 special (它将使用动态绑定)。然后编译器可能不会在first-name函数中使用尾调用优化。

这意味着您还需要知道变量符号是否被声明为特殊符号。

这是其中一个原因,全局特殊变量应该像*name*一样编写,以防止特殊声明那些应该是词汇变量的局部变量。在这种情况下,特殊声明也会阻止TCO。

我们最好写一下:

(defvar *name* '(susanne mustermann))