List 这种常见的Lisp代码是否与它们的';温斯顿/霍恩用LISP第三版重新教学?
他们这么说List 这种常见的Lisp代码是否与它们的';温斯顿/霍恩用LISP第三版重新教学?,list,time-complexity,lisp,common-lisp,reverse,List,Time Complexity,Lisp,Common Lisp,Reverse,他们这么说 (defun user-reverse (l) (if (endp l) nil (append (user-reverse (rest l)) (list (first l))))) 由于计算量为n(n+1)/2,因此不好 然后他们说这样走: (defun user-reverse (l &optional result) (if (endp l) result (user-reverse
(defun user-reverse (l)
(if (endp l)
nil
(append (user-reverse (rest l))
(list (first l)))))
由于计算量为n(n+1)/2,因此不好
然后他们说这样走:
(defun user-reverse (l &optional result)
(if (endp l)
result
(user-reverse (rest l)
(cons (first l) result))))
所以我在想,为什么你不能做这样的事:
(defun user-reverse (l)
(do ((new-list nil))
((endp l) new-list)
(push (pop l) new-list)))
这是一个坏习惯还是什么?还是抄袭了名单什么的?他们教了“Do”几个章节,想知道有没有LisPaS可以说这是标准的还是更坏的,或者他们的例子没有什么?基本上,我想知道他们的坏“n”例子是如何站起来的?有两个问题:
- 算法和数据结构的复杂性和效率
- 递归与循环
DO
。它既使用高效的运算符,又只受内存大小的限制。它不受堆栈大小的限制,因为它不执行任何递归调用
通常,在现实世界中,Lisp中的软件(->不是为教学目的编写的)会发现代码使用循环,因为TCO通常不适用于所有实现。例如,公共Lisp的ABCL实现在Java虚拟机(JVM)上运行。因为JVM不提供实现TCO的直接特性,所以JVM的编程语言实现通常不提供TCO。ABCL也不例外
dolist
可以使用dolist
编写循环版本:
(defun user-reverse (l &aux r)
(dolist (e l r)
(push e r)))
“在Lisp列表中,将其添加到列表末尾的成本很高。”。确切地说,
rplacd
既便宜又简单。从顶部节点发现终端节点的成本很高。另外,当然,append
复制了第一个列表的全部内容。好的,很酷,谢谢你的深入回答和更多!另外,谢谢你的提醒。非常好的信息,再次感谢您抽出时间为我解决一些问题!另一个与您的版本不同的地方是:它改变了变量绑定。这没有什么错,除非有:我的意思是,在很大程度上,变异状态的程序是否更糟糕是一个意见问题,但有时不这样做的程序更清晰(有时这样做的程序更清晰),也许编译器也更容易推理。