Vin*_*inn 2 recursion common-lisp apply
当我出于学习目的阅读代码时,我经常看到这样的函数:
(defun min-list (lst)
(cond ((endp (rest lst)) (first lst))
(t
(min (first lst) (min-list (rest lst))))))
Run Code Online (Sandbox Code Playgroud)
如果我在我的项目中编写这个函数,我会用apply
.
(defun min-list2 (lst)
(cond ((endp (rest lst)) (first lst))
(t
(apply #'min lst))))))
Run Code Online (Sandbox Code Playgroud)
当我用 测试这两个变体时time
,它们似乎执行相同的操作。
有关系吗?
他们使用不同的风格,但有不同的限制。
递归变体,正如它所写的那样,受到堆栈空间的限制(如果列表太长,有时会出现堆栈溢出)。可以将其重写为尾递归,在大多数 CL 实现中,尾递归将被优化为或多或少的不会增加堆栈的循环,但这不能保证可移植代码。
该apply
变体受到 的限制call-arguments-limit
,标准仅保证其至少为 50,尽管大多数实现的值要高得多。通常最好显式使用reduce
。
另一种也是惯用的解决方案是使用loop
、do
或某些库(例如iterate
或 )直接循环for
,这些通常是性能最高的(在重要的情况下)。