List 将列表作为函数参数传递,并从函数返回列表
我有以下代码:List 将列表作为函数参数传递,并从函数返回列表,list,lisp,common-lisp,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))) 目标是读取输入行并将其存储在列
(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
)。我做错了什么?append
不会修改它的参数,也就是说,因为您没有使用它的值,所以您没有做任何事情
(defun read-coords (&optional accumulation)
(let ((x (read-line)))
(if (string= x "0")
(nreverse accumulation) ; done
(read-coords (cons x accumulation)))))
(defvar *coords* (read-coords))
这是您的代码,具有更好的格式:
(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\u coords
的返回值是多少?函数包含隐式,因此它是最后一种形式。这里,最后一个表单是。根据测试结果,返回值在位置为,或在else位置为PROGN
的返回值。因此,测试失败时的返回值是通过调用(read_coords in)
获得的。当递归最终无误结束时,它必然位于IF
的then分支中,该分支在中返回。请注意,
中的在整个执行过程中从不被修改
事实上,它会根据输入创建一个新列表。换句话说,新列表是调用APPEND
返回的值,不幸的是,它从未存储在任何地方。计算没有任何副作用,其结果被丢弃。
您可能应该这样做:
(read_coords (append in (cons x nil)))
因此,新列表将作为参数传递给递归调用
评论
不要使用来定义局部变量。您需要在这里使用a-binding。否则,您将以依赖于实现的方式更改全局词法范围(除非您定义了名为x
的全局变量,这是不好的,因为它违反了特殊变量的命名约定,而特殊变量应该有*耳罩*
)。在函数中对全局变量进行变异可能会使其不可重入,这是非常糟糕的
(cons x nil)
要使用一个元素构建列表,只需使用:
最后,请注意,名称中不应使用下划线,而应使用破折号。因此,您的函数应该命名为read coords
,或者更好的命名为read coordinates
(equalp x "0")
尽管上面的说法是正确的,但最好在这里使用string=
,因为您知道返回字符串
演出
您一次又一次地追加一个列表,这将为正在读取的每个元素创建一个副本。对于一个可以用线性算法完成的任务,您的代码在时间和空间使用上是二次的。
此外,您正在使用一个尾部递归函数,其中一个简单的迭代将更清晰、更惯用。在公共Lisp中,我们通常不使用尾部递归过程,因为该语言提供了迭代控制结构,而且尾部合并优化不能保证总是应用(优化不是强制性的(这是一件好事)不会阻止实现提供它,即使它可能需要来自用户的附加声明)。最好在这里使用
我们在参数中传递一个输入流,该参数默认为。然后READ-LINE
在忽略错误的情况下读取行(由于第一个零)。如果发现错误,比如当我们到达文件末尾时,返回的值是零(由于第二个零)。当正在读取的行为零或等于“0”
时,循环结束。循环将读取到列表中的所有连续行累加起来。请修正缩进和排列。很抱歉,现在好点了吗?适度:-(请使用Emacs-它将正确缩进您的代码,并避免挂起括号。好的,我会试试;我不知道LISP编辑器,所以我使用常规notepadWow,这是一个很好的解释!我是LISP初学者,非常感谢您的努力:)@Karloss非常感谢。最好将nreverse
调用放在函数中。
(list x)
(equalp x "0")
(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))