list - 将列表作为函数参数传递并从函数返回列表

标签 list lisp common-lisp

我有以下代码:

(defun read_coords (in)
    (setq x (read-line))
    (if (equalp x "0")
        in
        (progn
            (append in (cons x nil))
            (read_coords in)
        )
    )
)

(setq coords (read_coords (cons nil nil)))

目标是读取输入行并将它们存储在列表中。问题是列表 coords 保持不变(因此只包含 NIL)。我做错了什么?

最佳答案

这是您的代码,格式更好:

(defun read_coords (in)
  (setq x (read-line))
  (if (equalp x "0")
      in
      (progn
        (append in (cons x nil))
        (read_coords in))))

(setq coords (read_coords (cons nil nil)))

现在,read_coords 的返回值是多少?函数包含隐式 PROGN ,因此它是最后一种形式。在这里,最后一种形式是 IF .根据测试的结果,返回值是 inPROGNelse 位置的返回值。因此,测试失败时的返回值是通过调用 (read_coords in) 获得的值。当递归最终无误结束时,它必然在 IFthen 分支中,它返回 in请注意,in 在整个执行过程中从未被修改

确实,APPEND根据其输入创建一个新列表。换句话说,新列表是调用 APPEND 返回的值,遗憾的是它从未存储在任何地方。计算是在没有任何副作用的情况下完成的,其结果将被丢弃。 您可能应该这样做:

(read_coords (append in (cons x nil)))

因此,新列表作为参数传递给递归调用。

备注

(setq x (read-line))

不要使用 SETQ定义局部变量。您需要使用 LET - 在这里绑定(bind)。否则,您将以依赖于实现的方式更改全局词法范围(除非您定义了一个名为 x 的全局变量,这很糟糕,因为它违反了特殊变量的命名约定,应该有*耳罩*)。在函数内改变全局变量可能使其不可重入,这是非常糟糕的。

(cons x nil)

为了构建一个只有一个元素的列表,只需使用 LIST :

(list x)

最后,请注意您不应在名称中使用下划线,而应使用破折号。因此,您的函数应该命名为 read-coords,或者更好的是 read-coordinates

(equalp x "0")

即使上面是正确的,在这里使用 string= 可能会更好,因为你知道 READ-LINE返回一个字符串。

性能

您一次又一次地附加一个列表,它为每个被读取的元素创建一个副本。对于可以使用线性算法完成的任务,您的代码在时间和空间使用方面是二次方的。 此外,您正在使用尾递归函数,其中简单的迭代会更清晰、更惯用。我们通常不在 Common Lisp 中使用尾递归过程,因为该语言提供了迭代控制结构,并且尾合并优化不能保证始终应用(优化不是强制性的(这是一件好事)不会阻止实现提供它,即使它可能需要用户的额外声明)。最好使用 LOOP这里:

(defun read-coordinates (&optional (input-stream *standard-input*))
  (loop for line = (read-line input-stream nil nil)
        until (or (not line) (string= line "0"))
        collect line))

我们在参数中传递一个输入流,默认为*STANDARD-INPUT* .然后 READ-LINE 读取行并忽略错误(感谢第一个 NIL)。如果发现错误,比如当我们到达文件末尾时,返回值为 NIL(多亏了第二个 NIL)。当读取的行为 NIL 或等于 “0” 时,LOOP 结束。循环将所有被读取的连续行累积到一个列表中。

关于list - 将列表作为函数参数传递并从函数返回列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40939053/

相关文章:

linux - kernel.h中的这段代码是什么意思?

Python 从另一个列表创建特定列表

emacs - 是什么让您想学习 Common Lisp?你想从中得到什么?

variables - 在 Scheme 语言中评估浮点变量

lisp - 我可以将Common Lisp用于SICP还是Scheme是唯一的选择?

python - % : 'list' and 'int' 的类型错误不支持的操作数类型

css - 如何使用 Bootstrap 4 在多列中拆分列表?

recursion - 为什么在传递否定参数时我的代码会卡在递归调用中?

scheme - Scheme 或 Common Lisp 中的牛顿平方根法

memory - 将操作码插入内存