LISP迭代到递归

时间:2018-01-10 12:47:16

标签: 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)))
    )
  )

有没有办法在没有loop的情况下以递归方式重写它?

2 个答案:

答案 0 :(得分:6)

用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)))))

答案 1 :(得分:5)

当然,任何循环都可以在递归中进行转换,但是按时读取整个文件是一个典型的迭代过程,所以我发现这个问题很难激发。

这是一个可能的递归版本,其中递归由内部函数管理:

)

如果文件的行数很大,则此解决方案容易出现堆栈溢出错误。

如果有一个可以执行尾部优化的编译器,下面的替代递归解决方案可以以迭代方式编译,可以避免堆栈溢出:

(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))))