Recursion LISP迭代到递归
我使用循环函数在LISP中写下了这个迭代代码:Recursion LISP迭代到递归,recursion,iteration,lisp,common-lisp,Recursion,Iteration,Lisp,Common Lisp,我使用循环函数在LISP中写下了这个迭代代码: (defun loadfile (filename) (with-open-file (stream filename) (loop for line = (read-line stream nil 'eof) until (eq line 'eof) collect line))) ) ) (defun load-file (filename) (with-open-file
(defun loadfile (filename)
(with-open-file (stream filename)
(loop for line = (read-line stream nil 'eof)
until (eq line 'eof)
collect line)))
)
)
(defun load-file (filename)
(with-open-file (stream filename)
(labels ((read-recursively ()
(let ((line (read-line stream nil 'eof)))
(if (eq line 'eof)
nil
(cons line (read-recursively))))))
(read-recursively))))
有没有一种方法可以在不使用循环的情况下,以递归的方式重写它?当然,任何循环都可以在递归中转换,但是每次读取一行完整的文件是一个典型的迭代过程,因此我发现这个问题很难解决 下面是一个可能的递归版本,其中递归由内部函数管理:
(defun loadfile (filename)
(with-open-file (stream filename)
(loop for line = (read-line stream nil 'eof)
until (eq line 'eof)
collect line)))
)
)
(defun load-file (filename)
(with-open-file (stream filename)
(labels ((read-recursively ()
(let ((line (read-line stream nil 'eof)))
(if (eq line 'eof)
nil
(cons line (read-recursively))))))
(read-recursively))))
如果文件的行数很大,此解决方案很容易出现堆栈溢出错误
如果有一个编译器可以执行尾部优化,那么可以以迭代方式编译以下替代递归解决方案,并可以避免堆栈溢出:
(defun load-file (filename)
(with-open-file (stream filename)
(labels ((read-recursively (read-so-far)
(let ((line (read-line stream nil 'eof)))
(if (eq line 'eof)
(reverse read-so-far)
(read-recursively (cons line read-so-far))))))
(read-recursively ()))))
相反,用“GOTO”来给他们一个惊喜:
(defun loadfile (filename)
(with-open-file (stream filename)
(prog (line lines)
repeat
(setf line (read-line stream nil))
(when line
(push line lines)
(go repeat))
(return (reverse lines)))))
是的,但它看起来像是一个需要递归方法的任务吗?是的,我确实使用了循环,但任务(不幸的是)清楚地说“不要使用循环、DO、DOLIST、DOTIMES”,我明白了;请注意,
tagbody
;-)显然没有限制啊,好吧,这是家庭作业,对吗?在现实生活中,为了在两行中实现这一点,我建议:文件必须只包含一行(可能是一行),因此我认为两种解决方案中的每一行都可以使用,对吗?@DouglasP仅包含一行?那么为什么要循环呢?只要调用readline
onceYes,我想尝试一下,以防我有更多行。非常感谢。