common Lisp学习笔记(十三)

lisp_chapter13

  • 13 Arrays, Hash Tables, and Proterty Lists

    • 13.2 array
    • 13.5 make-array
    • 13.6 string as vectors
    • 13.7 hash tables
    • 13.8 priority list
    • lisp toolkit: room
    • 13.11 coerce

13 Arrays, Hash Tables, and Proterty Lists

13.2 array

数组是内存中的一些连续的存储空间,一维的数组也叫做vector,第一个元素下标也是从0开始

注意数组与list的区别,list相当于链表,每个元素需要一个cons相当于两个空间,一个指向内容一个指向下一个 地址,而数组中每个元素只需要一个空间,每个数组前面有一个header,里面的信息有数组的长度,维数等。数组 的元素访问速度要快于list,因为可以直接通过下标计算地址来进行访问,而链表越往后的元素访问速度就越慢。 相比之下,list的优势是容易创建,可以通过递归或者迭代的方式创建,而且可以动态扩建,还有就是list可以使用 共享的cons,这也是数组不能实现的

  • 创建数组: (setf my-vec ‘#(tuning violin hello 11)),与list的区别是多了一个#
  • 输出

lisp中有一个全局变量*print-array*,如果该变量是t,则输出数组时可以看到每一个元素,如果置为nil,则输出 #<>的缩略形式

> (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 也可能为nil

:initial-element关键字是数组元素的初始值,:initial-contents则是一个用来初始化数组的list,长度必须 和数组的长度一样

> (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。比如我们只需要输出后面的序列而不需要返回序列的任何内容时可以使用

时间: 2025-01-12 08:22:00

common Lisp学习笔记(十三)的相关文章

Common Lisp学习笔记(六)

6 list data structure 首先注意cons的用法 (cons 'w '(x y z)) -> (w x y z) 但是想在list的结尾添加一个元素就不能这样实现,eg, (cons '(w x y) 'z) -> ((w x y) . z) 6.3 the APPEND function append函数可以参数是两个list,并将两个list的元素合并在一起,如果其中有一个是nil,则结果和另一个list相同 > (append '(a b) '(c d)) (a

common Lisp学习笔记(十二)

12 Structure and The Type Syetem 12.2 typep, type-of 12.3 defining structures 12.5 accessing, modifying structs 12.6 kwargs to constructor functions 12.7 修改结构体定义 12.8 print func for structs 12.9 equality of structs 12.10 inheritance 12 Structure and

Common Lisp 学习笔记

特殊操作符.函数.宏 0.0 format CL-USER>(format t "hello world") ;t=>*standard-output* hello world NIL CL-USER>(format t "~a:~10t~a" "This is" "a shinny day") This is: a shinny day NIL ~a=>美化输出(如字符串去引号.关键字去前导冒号),消

Common Lisp学习笔记(九)

9 Input/Output 9.2 string 9.3 format 9.4 read 9.5 yes-or-no-p 9.6 with-open-file 9.7 writing files with with-open-file 9.8 parameters to format directives 9.9 file EOF 9 Input/Output 9.2 string string在lisp中用双引号括起来,它的值也是自己本身,和数字一样,string不是symbols stri

Common Lisp学习笔记(十一)

11 Iteration and Block Structure 11.2 dotimes and dolist 11.4 recursive, iterative 11.6 比较dolist, mapcar, recursion 11.7 DO macro 11.8 隐式赋值的好处 11.9 do* 11.11 implicit blocks lisp toolkit: time 11.13 optional args 11.14 rest args 11.15 keyword args 11

Common Lisp学习笔记(七)

7 Applicative Programming 7.2 funcall 7.3 mapcar 7.4 manipulating tables with mapcar 7.5 lambda expressions 7.6 find-if 7.7 my-assoc 7.8 remove-if, remove-if-not 7.9 reduce 7.10 every debug tool: trace 7.11 operating on multiple lists 7.12 function函数

Common Lisp学习笔记(八)

8 Recursion 8.11 recursive templates 8.12 variations on the basic templates 8.13 trees and car/cdr recursion 8.14 helping functions 8 Recursion (defun fact (n) (cond ((zerop n) 1) (t (* n (fact (- n 1)))))) ex 8.4 (defun laugh (n) (cond ((zerop n) ni

java之jvm学习笔记十三(jvm基本结构)

java之jvm学习笔记十三(jvm基本结构) 这一节,主要来学习jvm的基本结构,也就是概述.说是概述,内容很多,而且概念量也很大,不过关于概念方面,你不用担心,我完全有信心,让概念在你的脑子里变成图形,所以只要你有耐心,仔细,认真,并发挥你的想象力,这一章之后你会充满自信.当然,不是说看完本章,就对jvm了解了,jvm要学习的知识实在是非常的多.在你看完本节之后,后续我们还会来学jvm的细节,但是如果你在学习完本节的前提下去学习,再学习其他jvm的细节会事半功倍. 为了让你每一个知识点都有迹

Swift学习笔记十三:继承

一个类可以继承(inherit)另一个类的方法(methods),属性(property)和其它特性 一.基本语法 class Human{ var name :String init(){ name = "human" println(name) } func description(){ println("name:\(name)") } } class Student:Human{ var score = 0 init(){ super.init() name