Recursion 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

我使用循环函数在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 (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,我想尝试一下,以防我有更多行。非常感谢。