LISP迭代到递归

Fre*_*d_2 2 lisp iteration recursion 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)))
    )
  )
Run Code Online (Sandbox Code Playgroud)

有没有办法以loop递归的方式重写它?

Rai*_*wig 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)))))
Run Code Online (Sandbox Code Playgroud)


Ren*_*nzo 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))))
Run Code Online (Sandbox Code Playgroud)

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

如果一个人有能够执行尾优化编译器,以下替代递归溶液可以在迭代的方式被编译并避免堆栈溢出:

(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 ()))))
Run Code Online (Sandbox Code Playgroud)