我要管理這種情況: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)
)中寫的是浮點數列表。
您可能有一個全局變量來存放所有點的列表。 –