2.20

练习 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)。给了定义:

(define (g . w) <body>)

过程g可以用0个或多个参数调用。如果求值:

(g 1 2 3 4 5 6)

那么在g的体里,w将是表(1 2 3 4 5 6)。

请采用这种记法形式写出过程same-parity,它将一个或者多个整数为参数,返回所有与其第一个参数有着同样奇偶性的参数形式的表。例如:

(same-parity 1 2 3 4 5 6 7)
(1 3 5 7)

(same-parity 2 3 4 5 6 7)
(2 4 6)

首先,很容易想到,函数的签名是这样的:

(define (same-parity x . w) 

)

为了方便,想到使用递归。即假设求出了 (same-parity x . w1, ... wn-1),然后再求出 (same-parity x . w1, ..., wn-1, wn) 就只剩下一步之遥了。

但是这要求取 w 的前 n-1 项,以及最后一项。这和基本操作 car 以及 cdr 的操作正好相反,于是想到了利用前面练习中实现的 reverse,从而可以更简单地处理。

于是可以反过来思考,假设先求出了 w 的后 n-1 项,最后处理 w 的第一项。于是,使用 car 和 cdr 就能方便地操作:

(define (same-parity x . w)
    (define (same-parity-list x lst) 
        (if (<= (length lst) 0)
            '()
            (if (= (mod x 2) (mod (car lst) 2))
                (cons (car lst) (same-parity-list x (cdr lst)))
                (same-parity-list x (cdr lst))
            )
        )
    )

    (cons x (same-parity-list x w))
)


(same-parity 1 2 3 4 5 6 7)
(same-parity 2 3 4 5 6 7)

results matching ""

    No results matching ""