我要管理这种情况:Common Lisp中,列表处理(追加等)
(defun make-point (a b)
(cons a b))
这个函数创建笛卡尔轴上的点之一(我省略通用控件方便)。我怎样才能实现一个功能,每次调用点时,它都会更新一个所有点被添加的列表?
E.g.
'()
((1.1))
((1.1)(2.4))
((1.1)(2.4)(4.5))
我将需要列表作为以下函数的参数。
我要管理这种情况:Common Lisp中,列表处理(追加等)
(defun make-point (a b)
(cons a b))
这个函数创建笛卡尔轴上的点之一(我省略通用控件方便)。我怎样才能实现一个功能,每次调用点时,它都会更新一个所有点被添加的列表?
E.g.
'()
((1.1))
((1.1)(2.4))
((1.1)(2.4)(4.5))
我将需要列表作为以下函数的参数。
你定义一个变量:
(defvar *points* '())
周围变量的名称(称为“耳罩”)中的星号是CL很强的约定来表示变量声明特殊,这是当案件使用DEFVAR
/DEFPARAMETER
。在这里我使用的是DEFVAR
,因为如果我需要重新加载代码所在的编译单元,我不想将列表中的列表重置为空列表。
然后,您可以为程序员提供了一个接口,抽象点的该列表:
(defun clear-all-points()
(setf *points* nil))
(defun add-point (point)
(push point *points*))
在这里你可以看到,我给定点存储点的名单,这是自然的前与列表一起工作的方式;在最后添加东西,要求你遍历列表,这是浪费的,大部分时间,没有必要。此外,究竟你添加了新的元素可能会改变如何使用点的列表:如果您实现add-point
作为
(setf *points* (append *points* (list point)))
...然后*points*
引用的列表是复制,如果您之前在另一个地方存储了*points*
,您现在有两个要点列表(我不是说这里是对还是错,只是解释发生了什么);
但是,如果你发生变异的名单:
(setf *points* (nconc *points* (list point)))
...那么你就可以分享不同对象之间的列表,每当他们阅读列表中,他们将有最多最新所有点的列表。
您可能还需要考虑两种方法将使用多少内存。如果通过复制进行追加,使用APPEND
,则前一列表最终将被垃圾收集器收回;如果您频繁添加点,您将开始以可能会降低性能的方式来垃圾内存。
如果您需要在不考虑NCONC
的情况下最终考虑使用队列或数组。 基本队列可以在列表的顶部被简单地实现,通过一个队列对象这仅仅是一个缺点细胞,其中car
是基础列表的第一小区和cdr
是的最后利弊细胞相同的列表。当您将追加一个元素x
到列表(e0 ... en)
,你从这个状态进入:
(e0 . (... (en . nil) ...))
^first ^last
...这一个
(e0 . (... (en . (x . nil)) ...))
^first ^last
你可以尝试将其实现为另一种锻炼。
然后,你可以保持你的功能不变(但缩进);你可能将不得不作出点,而将它们添加到全局列表,因此是很有意义让事情分开:
(defun make-point (a b)
(cons a b))
如果你需要它,你可以定义结合了动作的辅助功能:
(defun add-new-point (a b)
(add-point (make-point a b)))
此外,请注意空格是重要的:您在所需的输出(例如(1.1)
)中写的是浮点数列表。
您可能有一个全局变量来存放所有点的列表。 –