列表

2016-12-18  本文已影响0人  Saru様

1. 构造(Conses)


cons真正所做的事情是把两个对象结合成一个具有两部分的对象,称为cons对象
概念上来说是一对指针,carcdr

2. 等式(Equality)


每一次调用cons时,Lisp会配置一块新的内存给两个指针,所以使用通常参数调用cons两次,会产生出两个数值一样的两个对象。

3.为什么Lisp没有指针


4. 建立列表(Buiding Lists)


5. 存取(Access)


列表中的元素是从0开始编号的

7. 映射函数(Mapping Functions)


映射函数就是对一个列表中的所有元素做函数调用。

8. 树(Trees)


cons对象可以想象成二叉树,car代表左子树,cdr代表右子树。
操作树的函数通常使用carcdr同时做递归,这种函数被称为双重递归(diubly recursive)

9. 理解递归(Understanding Recursion)


检查两件事来判断递归函数是正确的:

10. 集合(Sets)


列表是表示小集合的好方法
集合中没有顺序的概念,所以不需要保留元素元素的顺序

11. 序列(Sequences)


一系列有特定顺序的列表。

12. 栈(Stacks)


13. 点状列表(Dotted Lists)


用点(.)来分割开的列表,称为点状列表。点状列表不是一个正规列表。
点状列表是一个成对的Cons对象,而正规列表不是。
点状列表可以作为类似映射表的方式使用,因为是成对的,而不像正规列表是连接的。

> (setf pair (cons 'a 'b))
(A . B)

14. 关联列表(Assoc-lists)


一个由cons对象组成的列表称之为关联列表(assoc-listor alist)。关联列表很慢,但在初期的程序中使用很方便。

> (setf trans '((+ . "add")))
> (assoc '+ trans)
(+ . "add")

15. 垃圾(Garbages)


列表提供顺序存取而不是随机存取,所以会比数组慢。
Cons对象倾向于用指针表示,所以访问一个列表意味着访问一系列的指针。
虽然这样比简单地像数组一样增加索引值慢,但所话费的代价与配置及回收Cons单元比起来小多了。

垃圾回收可以让程序员不比现实的使用allocate及dellocate进行内存管理,而是由Lisp进行内存管理,这样有效的避免内存泄漏及悬垂指针的问题。

但垃圾回收也是需要代价的。所以如果需要写出高性能的Lisp程序是需要时时考虑对Cons对象的使用,因为Cons对象始终是需要被回收的。

有些Lisp实现回收的Cons代价很大,而有的Lisp实现,内存管理相当好,以至于使用cons比不适用cons更快。

习题(Exercises)


  (defun new-union (lst1 lst2)
    (if (null lst2)
      lst1
      (if (null (member (car lst2) lst1))
        (append (new-union lst1 (cdr lst2))
              (cons (car lst2) nil))
        (new-union lst1 (cdr lst2)))))
  (defun occurrences (ls)
    (let ((acc nil))
      (dolist (obj ls)
        (let ((p (assoc obj acc)))
          (if p
            (incf (cdr p))
            (push (cons obj 1) acc))))
      (sort acc #'> :key #'cdr)))
  1. 因为member使用eql来比较对象

  (defun our-cons (x y)
    (let ((ls '(nil .nil)))
      (setf (car ls) x
          (cdr ls) y)
      ls))
   (defun our-list (&rest items)
       (our-list-0 items))

   (defun our-list-0 (lst)
       (if lst
           (cons (car lst)
             (our-list-0 (cdr lst)))))
(defun our-length (lst)
  (if lst
      (+ 1 
         (our-length (cdr lst)))
    0))
(defun our-member (target lst)
  (if lst
      (if (eq target (car lst))
          lst
        (our-member target (cdr lst)))))
  (defun n-elts (elt n)
      (if (> n 1)
            (cons n elt) ;; 将list修改为cons,因为list本身会使用多个cons
      elt))
  (defun showdots (lst)
      (showdots-rec lst 0))

  (defun showdots-rec (lst n)
  (if lst
      (progn
        (if (atom (car lst))
            (format t "(~A . " (car lst))
          (progn
            (format t "(")
            (showdots-rec (car lst) 0)
            (format t " . ")))
        (showdots-rec (cdr lst) (+ 1 n)))
    (progn
      (format t "nil")
      (dotimes (j n)
        (format t ")")))))

上一篇 下一篇

猜你喜欢

热点阅读