可变长的参数

(a b c) //这里是固定参数 b c
(a b c . d) //这里就是可变长参数 d

在(a b c . d)中b c 是正常的参数 ,然而d是一个列表

例:

一个简单的加法最少两个数的加法

> (define (add a b . c)
    (define (tem-add x y l li)
       (if (= l 0)
          (+ x y)
         (tem-add (+ x y) (car li) (- l 1) (cdr li))))
    (let ((len (length c)))
      (tem-add a b len c)))
> (add 1 2 3)
6
> (add 1 2 3 4)
10
> (add 2 3)
5
> (add 1 2 3 4 5 6 7 8 9)
45

对表的映射

将某个操作用于一个表

> (define (map li a)
    (if (null? li)
        (list)
        (cons (+ (car li) a)
          (map (cdr li) a))))
> (map (list 1 2 3 4) 20)
(21 22 23 24)
> (map (list 0 1 2 3 4 5 6 7 8 9) 10)
(10 11 12 13 14 15 16 17 18 19)

层次性结构

对象((1 2) 3 4)

可以认为是(cons (list 1 2) (list 3 4)) 构造出来的
这也是一种树
(list 1 2) 3 4 是在第一层
1 2 是在第二层

> (length (cons (list 1 2 3) (list 1 2 3 4 5)))
6
> (length (car (cons (list 1 2 3) (list 1 2 3 4 5))))
3
> (length (cdr (cons (list 1 2 3) (list 1 2 3 4 5))))
5
> (length (cdr (cdr (cons (list 1 2 3) (list 1 2 3 4 5)))))
4

length计算这个节点的子节点个数

> (length (list (list 1 2 3) (list 23)))
2

pair? 是scheme中判断操作数是不是序对

> (pair? 1)
#f
> (pair? (list))
#f
> (pair? (list 1))
#t
> (pair? (list 2))
#t

现在构造一个过程count-leaves 用来计算一个数的所有树叶的个数

> (define (count-leaves tree)
    (cond
      ((null? tree) 0)
      ((not (pair? tree)) 1)
      (else (+ (count-leaves (car tree)) 
               (count-leaves (cdr tree)))))))
> (count-leaves (list 1 2 3 4))
4
> (count-leaves (list 1 2 3 (list 1 2 3)))
6
> (length (list 1 2 3 (list 1 2 3)))
4
> (length (list 1 2 3 4))
4

不过这个是递归版

迭代版:

> (define (count-leaves tree)
    (define (fun count tree-tem all-tem)
      (if (pair? tree-tem)
        (if (= (length tree-tem) 1)
            (fun count (car tree-tem) all-tem)
            (fun count (car tree-tem) (cons (cdr tree-tem) all-tem)))
        (if (pair? all-tem)
            (fun (+ 1 count) (car all-tem) (cdr all-tem))
            count)))
    (if (pair? tree)
        (fun 1 (car tree) (cdr tree))
        0))

> (count-leaves (list 1 2))
2
> (count-leaves (list 1 2 (list 1 2)))
4
> (count-leaves (list 1 2 (list 1)))
3
> (count-leaves (list (list 1 1) (list (list 1 1 1) 1 1 (list 1 1 1))))
10
(count-leaves (list (list (list (list 1) 1) 1) 1))
4

其中第六行 cons 可以用append代替

> (define (count-leaves tree)
    (define (fun count tree-tem all-tem)
      (if (pair? tree-tem)
        (if (= (length tree-tem) 1)
            (fun count (car tree-tem) all-tem)
            (fun count (car tree-tem) (append (cdr tree-tem) all-tem)))
        (if (pair? all-tem)
            (fun (+ 1 count) (car all-tem) (cdr all-tem))
            count)))
    (if (pair? tree)
        (fun 1 (car tree) (cdr tree))
        0))
> (count-leaves (list 1))
1
> (count-leaves (list 1 3 4))
3
> (count-leaves (list 1 3 4 (list 1 2 3 4)))
7
> (count-leaves (list 1 3 4 (list 1 2 3 (list 1 1 1))))
9
> (count-leaves (list 1 3 4 (list 1 (list 9 9 9) 2 3 (list 1 1 1))))
12

append

将表的内容连接起来

> (append (list 1 2 3) (list 1))
(1 2 3 1)
> (append (list 1 2 3) (list 1) (list 2 2 2))
(1 2 3 1 2 2 2)
> (append (list 1 1 1) (list (list 2 2 2) (list 3 3 3)))
(1 1 1 (2 2 2) (3 3 3))

cons

将第一个表加入到第二个表里

> (cons (list 1 2 2) (list 8 8 8 ))
((1 2 2) 8 8 8)

list

将表连接起来形成新的表

> (list (list 1 1 1 1 1) (list 2 2 2 2 2 2))
((1 1 1 1 1) (2 2 2 2 2 2))

对树的映射

与对表的映射差不多


> (define (scale-tree tree factor)
    (cond
      ((null? tree) (list))
      ((not (pair? tree)) (+ factor tree))
      (else (cons 
              (scale-tree (car tree) factor)
              (scale-tree (cdr tree) factor)))))
> (scale-tree (list 1 2 3 (list 3 4 5) (list 6 7 8 (list 8 9 0))) 10)
(11 12 13 (13 14 15) (16 17 18 (18 19 10)))

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

基本语法define与cond 上一篇
常用判断 下一篇