scheme层次性数据和闭包

该小节提到了通过序对构建表——list,多个序对,可以通过层层嵌套的方式,(1 (2 (3 (4 ……))))构建一个表。
由于我还是计算机程序的初学者,我很好奇其他的语言是否也是这样做的?但这个问题只能暂时滞留了,我得先学完scheme才有精力去研究其他语言。
针对list,有很多配套的操作需要学习,例如遍历,检索等。
练习2.17 请定义过程list-pair,它返回只包含给定(非空)表里最后一个元素的表:

点击查看代码
;不断取cdr直到list为null,返回上一个值
(define (last-pair list)
    (if (null? (cdr list))
            list
            (last-pair (cdr list))
        )
    )
练习2.18 请定义出过程reverse,它以一个表为参数,返回的表中所包含的元素与参数表相同,但排列顺序与参数表相反:
点击查看代码
;跟2.17的思路相近,取cdr直到空值,然后返回来car期间的list
(define (reverse list)
        (define (rev item list)
            (if (null? list)
                item
                (rev (cons (car list) item) (cdr list))))
        (rev '() list))

练习2.19 考虑1.2.2节中的兑换零钱方法计数程序。我们希望重写出程序cc,使其第二个参数是一个可用硬币的币值表,而不是一个指定可用硬币种类的整数,而后我们就可以针对各种货币定义出一些表。
(define us-coins (list 50 25 10 5 1))
(define uk-coins (list 100 50 20 10 5 2 1 0.5))
然后我们就可以通过如下方式调用cc:
(cc 100 us-coins)
这需要对cc进行一定修改:

点击查看代码
(define (cc amount coin-values)
    (cond (( = amount 0) 1)
          ((or (< amount 0) (no-more? coin-values)) 0)
          (else
            (+ (cc amount 
                    (except-first-denomination coin-values))
                (cc (- amount (first-denomination coin-values))
                    coin-values)))))
;参考1.2.2节的思路,当兑换费用为0时,认为有1种兑换方式,而兑换费用小于0或币种等于0时,有0种兑换方式
;因此这里判断币种是否为0,即列表是否为空
(define (no-more? x)
    (null? x))
;依旧是1.2.2的思路,总方案为排除了某一面值的硬币后的分配方案+总值扣掉某一硬币面值后所有种类的分配方案
;对应到表中就是cdr列表,减少币种
;或者car列表值,使总值每次减去一种币值
(define (except-first-denomination x)
    (cdr x))
(define (first-denomination x)
    (car x))
由此发现表coin-values的排列顺序并不影响cc给出的回答,因为整体思路还是遵循1.2.2里的树状图思维,树叶的发散不会因为币值排列受到影响,只是每片树叶发散的值会有变化。

练习2.20 过程+、*和list可以取任意个数的实际参数,定义这类过程的一种方式是采用一种带点尾部记法形式的define。在一个过程定义中,如果在形式参数表的最后一个参数之前有一个点号,那就表明,当这一过程被实际调用时,前面各个形式参数(如果有的话)将以前面的各个实际参数为值,与平常一样。但最后一个形式参数将以所有剩下的实际参数的表为值。例如,假如我们定义了:
(define (f x y . z)
body)
过程f就可以用两个以上的参数调用,如果求值:
(f 1 2 3 4 5 6)
那么在f的体里,x=1,y=2,而z将是表(3 4 5 6)
请采用这种记数形式写出过程same-parity,它以一个表或者多个整数为参数,返回与其第一个参数有着同样奇偶性的参数形成的表。

点击查看代码
(define (even? x)
    ( = (remainder x 2) 0))
(define (same-parity x . y)
    (if (even? x)
        (cons x (evenlist y))
        (cons x (oddlist y))
    ))
;根据题意,y为一个序对,对y进行筛选
(define (evenlist list)
    (if (null? list)
        list
        (if (even? (car list))
        (append  (cons (car list) '())(evenlist (cdr list)))
        (evenlist (cdr list))
        )))
(define (oddlist list)
    (if (null? list)
        list
        (if (even? (car list))
        (oddlist (cdr list))
        (append  (cons (car list) '())(oddlist (cdr list)))
        )))
posted @ 2025-12-11 18:16  檐上落白luckin  阅读(0)  评论(0)    收藏  举报