common Lisp學習筆記(十三)

lisp_chapter13數組

13 Arrays, Hash Tables, and Proterty Lists

13.2 array

數組是內存中的一些連續的存儲空間,一維的數組也叫作vector,第一個元素下標也是從0開始cookie

注意數組與list的區別,list至關於鏈表,每一個元素須要一個cons至關於兩個空間,一個指向內容一個指向下一個 地址,而數組中每一個元素只須要一個空間,每一個數組前面有一個header,裏面的信息有數組的長度,維數等。數組 的元素訪問速度要快於list,由於能夠直接經過下標計算地址來進行訪問,而鏈表越日後的元素訪問速度就越慢。 相比之下,list的優點是容易建立,能夠經過遞歸或者迭代的方式建立,並且能夠動態擴建,還有就是list可使用 共享的cons,這也是數組不能實現的app

  • 建立數組: (setf my-vec '#(tuning violin hello 11)),與list的區別是多了一個#
  • 輸出

lisp中有一個全局變量*print-array*,若是該變量是t,則輸出數組時能夠看到每個元素,若是置爲nil,則輸出 #<>的縮略形式dom

> (setf *print-array* nil)
nil

> my-vec
#<vector {204844}>

> (setf *print-array* t)
t

> my-vec
#(tuning violin hello 11)
  • access elements

aref能夠訪問數組的元素,相似於list中nth的用法函數

> (aref my-vec 1)
violin

> (setf (aref my-vec 1) 'piano)
piano

一些函數是數組和list均可以用的,如length, reverse, find-if等操作系統

另外一些函數只能用於list,如car/cdr, member, 和其餘集合函數等設計

13.5 make-array

make-array建立並返回一個新的數組,如(make-array 5)建立長度爲5的數組。若是不聲明元素的初始值,可能爲0 也可能爲nilcode

:initial-element關鍵字是數組元素的初始值,:initial-contents則是一個用來初始化數組的list,長度必須 和數組的長度同樣orm

> (make-array 5 :initial-element 1)
#(1 1 1 1 1)

> (make-array 5 :initial-contents '(a e i o u))
#(a e i o u)

13.6 string as vectors

字符串是一種特殊的vector,對數組可使用的函數均可以對string使用遞歸

(length "hello") -> 5
(reverse "hello") -> "olleh"
(aref "hello" 1) -> #\e

注意string的每一個元素例如#\e,都是char類型,字符類型不須要使用',由於它們的值都是自身

#\k -> #\k
(type-of #\k) -> standard-char

由於字符串裏每一個元素都是字符類型,因此用setf對元素賦值的時候只能用char類型,不然會報錯

13.7 hash tables

哈希表功能相似association list,可是訪問速度比較快,由於哈希表是用數組實現的

  • 哈希表只能經過make-hash-table函數來建立
    > (setf h (make-hash-table))
    #<eql hash table ...>
    
  • (gethash key hash-table): gethash函數返回key的哈希值,能夠用setf對其賦值
    > (setf (gethash 'john h) '(hello world))
    (hello world)
    > (setf (gethash 'mary h) '(good luck))
    (good luck)
    
    > (gethash 'john h)
    (hello world)
    t
    

gethash函數返回兩個值,第一個是哈希值,若是key不存在則返回nil。第二個值爲t或者nil, 表示key存在或者不存在。這種設計是由於有可能某個key的哈希值自己就是nil,這樣就沒法判斷這個key是否存在

  • (describe h): 返回哈希表的一些有用信息
    > (describe h)
    #<eql hash table ...> is a hash-table
    it currently has 2 entries and 65 buckets.
    

13.8 priority list

在lisp中,每一個symbol都有一個priority list. priority list能夠看做是一系列的鍵值對,每一個key稱爲indicator, priority list形如(indicator1 value1 indicator2 value2 ...)

priority list通常在比較舊的lisp中使用,如今能夠用association list或者hash table來代替

  • (get symbol indicator [default]): 獲取某個indicator對應的值
    (setf (get 'fred 'sex) 'male)
    (setf (get 'fred 'age) 23)
    
    > (describe 'fred)
    fred is a symbol
    its age property is 23
    its sex property is male
    

get函數是用eq來對key進行比較的,因此indicator不能是數字

get函數還能夠有第三個參數,即若是key找不到時的缺省值,能夠經過提供第三個參數來區別一個indicator不存在 或者是存在但值爲nil的狀況,由於這兩種狀況都是返回nil

(setf (get 'mabel 'siblings) nil)
(get 'mabel 'siblings 'unknown) -> nil
(get 'clare 'siblings 'unknown) -> unknown
  • (symbol-plist symbol): 返回符號的property list
    > (symbol-plist 'fred)
    (age 23 sex male)
    
  • (remprop symbol indicator): remove property, 刪除某個鍵值對
    (remprop 'fred 'age)
    (get 'fred 'age) -> nil
    

ex 13.8

(setf *hist-array* nil)
(setf *total-points* 0)

(defun new-histogram (num-bins)
  (setf *total-points* 0)
  (setf *hist-array* (make-array num-bins :initial-element 0))
  t)

(defun record-value (n)
  (incf *total-points*)
  (if (and (>= n 0) (< n (length *hist-array*)))
    (incf (aref *hist-array* n))
    (error "value ~S out of bounds." n)))

(defun print-hist-line (n)
  (format t "~&~2S [~3S] " n (aref *hist-array* n))
  (dotimes (i (aref *hist-array* n))
    (format t "*")))

(defun print-histogram ()
  (dotimes (i (length *hist-array*))
    (print-hist-line i))
  (format t "~&    ~3D total" *total-points*))

> (new-histogram 11)
t
> (dotimes (i 200) (record-value (random 11)))
nil
> (print-histogram)

lisp toolkit: room

lisp有幾種不一樣的方法來獲取更多的內存,一種是從新聲明一些之前用過但再也不使用的空間,即垃圾回收,還有一種 是讓操做系統分配更多的內存

(gc) 函數可讓lisp立刻開始垃圾回收

(room) 函數顯示當前的內存使用狀況

13.11 coerce

coerce函數能夠將一列元素轉化爲另外一種類型,如list類型轉爲string類型

> (coerce "cookie" 'list)
(#\c #\o #\o #\i #\e)
> (coerce '(#\h #\i) 'string)
"hi"
> (coerce '(foo bar baz) 'vector)
#(foo bar baz)

建立一個string的另外一個方法是用make-array, 用關鍵字:element-type設定元素類型爲string-char

> (make-array 3 :element-type 'string-char :initial-content '(#\m #\o #\m))
"mom"

對於大部分applicative operators,例如find-if, reduce, 均可以對任何種類的sequence使用,不侷限於list。 可是mapcar只能用於list, map能夠用於任何sequence,與mapcar的區別是第一個參數是返回的序列的類型

> (map 'list #'+ '(1 2 3 4) '(10 20 30 40))
(11 22 33 44)

若是map的第二個參數是nil,則返回nil。好比咱們只須要輸出後面的序列而不須要返回序列的任何內容時可使用

相關文章
相關標籤/搜索