Program Structure 笔记10 (序列数据的表示及处理)

Program Structure 笔记10 (序列数据的表示及处理)

  (作者:colinboy  Email:cybbh@163.com) 2008.5.20

(内容难免出现错误或一些专业词汇使用不当,只是个人笔记,能理解总体内容就好)

 

前面说过可以用list/cons/append构建序列(以后称为表),他们各自完成的功能如下:

(list (□ □) (△ △))  -->  ((□ □) (△ △))

(cons (□ □) (△ △))  -->  ((□ □) △ △)

(append (□ □) (△ △))  -->  (□ □ △ △)

 

list是用来构建一个表,每个参数为一个节点.

cons可以当作一种递归的表构造函数.

append用来把几个表连接成一个整体.

 

cons的实现:

我们实现一个称为kons的函数来模拟cons.

同时也实现karkdr来模拟carcdr.

 

(define (kons x y)

   (lambda (which)

     (cond ((equal? which 'car) x)

           ((equal? which 'cdr) y)

     (else (error "oh my god!" which)))))

 

(define (kar pair)

      (pair 'car))

 

(define (kdr pair)

      (pair 'cdr))

 

kons返回一个过程!

(define fraction (kons 5 6))

(kar fraction)  -->  5

(kdr fraction)  -->  6

 

当然,我们只是模拟了cons,scheme,cons是语言内置的,一般没人会自己实现一个cons使用.

 

 

se的实现:

se是用来把多个wordsentense组成一个新的sentense.(sentense类似字符串,word类似字符)

 

(se 'a 'b 'c 'd 'e)  -->  (a b c d e)

返回的结果好像表? 好像和执行(list 'a 'b 'c 'd 'e)一样.下面我们来实现一个se,看一看se内部是如何组织的.

 

(define (se a b)

   (cond ((word? a) (se (list a) b))

         ((word? b) (se a (list b)))

   (else (append a b))))

 

(se 'a 'b)  -->  (a b)

 

我们已经实现了se,不过看起来有点奇怪.. 比如输入(se 'a 'b 'c)就会... ,其实是实现了一个只能带2个参数的se.

 

我们发现se其实就是一个表,se的工作就是把输入的word以及sentence转换成表然后连接起来.

知道了se如何工作的,我们就来实现一个更好的se,让它能接受n多个参数.

 

(define (myse . words)

   (cond ((null? words) '())

         ((list? (car words)) (append (car words) (apply myse (cdr words))))

   (else (append (list (car words)) (apply myse (cdr words))))))

 

,发现了一点奇怪的语法, myse的声明为(myse . words),有个特殊的 . 符号,猜测大概这个符号意思就是后面的参数个数是不定的(其实就是).

 

(myse 'a 'b '(c d) 'e 'f)  -->  (a b c d e f)

 

为了测试一下我们实现的myse是否真的能当作真正的se使用,可以编写一点测试代码

(define test (myse 'a 'b 'c '(d e f) 'g))

(first test)  -->  a

(butfirst test)  -->  (b c d e f g)

(butlast test)  -->  (a b c d e f)

 

我们惊奇的发现,一些作用于se的函数都能用在myse构建的sentence,这证明我们实现的myse和语言内置的se的原理是一样的.看来距离实现一个scheme解释器更近一步了......

 

 

box-and-pointer(以下简称BAP)

BAP是一种用来表示表结构的图

例如下面的表:

((a (b) c) () d e (((f))))

 

BAP表示的图为:

 

()表示空表,不表示空"",就如上面的BAP图所示.

 

((3 . 4))是否表示一个表? 当然是,它表示一个只有一个元素的表,并且这个元素为一个pair.可以用(list (cons 3 4))构建出这个表.

 

(())表示一个表,这个表有一个元素,并且这个元素是一个空表.可以用(list ())构建出此表.

 

一些scheme函数:

pair? 判断一个数据是否是pair.

list? 判断一个数据是否是list.

null? 判断是否是空表.

empty? 判断是否是空的word或空的sentence.

 

在以前讲的数据处理形式中,说过scheme3种基本数据处理形式,every keepaccumulate.

3种基本处理形式在scheme中都有对应函数,

(every (lambda (wd) (se wd wd)) '(my name))  -->  (my my name name)

(keep (lambda (num) (> num 5)) '(1 2 3 4 5 6 7 8))   -->  (6 7 8)

(accumulate + 0 '(1 2 3 4 5))   -->  15

 

对于list,也同样存在这样的处理函数,对应如下

every  -->   map

keep   -->  filter

accumulate对于两者都适用.

 

(map (lambda (wd) (se wd wd)) '(my name))  -->  ((my my) (name name))

every对比,发现map的行为和every是有区别的.

 

map可以接受多个参数.

(define (word w1 w2 w3) (se w1 w2 w3))

(map word '(1 2 3) '(a b c) '(1 2 3))  -->  ((1 a 1) (2 b 2) (3 c 3))

 

如果输入的数据多个数据大小不一致,会一第一个数据为准.

(map word '(1 2) '(a b c d) '(1 2 3 4))  -->  ((1 a 1) (2 a 2))

 

 

创建可以接收多个输入参数的函数:

map函数可以接受多个参数,这是怎么实现的?

 

(define (add-nums . nums)

   (if (null? nums) 0

       (+ (car nums) (apply add-nums (cdr nums)))))

 

(add-nums 1 2 3 4 5)  -->  15

 

对于lambda语句,可以用如下形式:

(lambda args ````````)

(lambda (val1 . args) `````````````)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值