问题描述
Do not use any predefined predicates(functions).
sash> (split '(a b c d e f g h i k) 3)
sash> ((a b c) (d e f g h i k))
题目要求“自己动手,丰衣足食“。
解法
尾递归实现
(define split (lambda (ls n) (let f ([i 1] [ls1 '()] [ls2 ls]) (cond [(> i n) (list (reverse ls1) ls2)] [else (f (+ i 1) (cons (car ls2) ls1) (cdr ls2))]))))
上面用到了
reverse
,貌似不满足题目要求。普通递归实现
将上面
ls1
的累积过程改成普通递归形式。在一次遍历实现,需要借助复杂的控制才能实现。如果两次遍历,第一次遍历得到前n个元素的列表,第二次得到其余元素的列表,两次结果cons得到最终结果。目前没想到满意的方案,暂为空
CPS实现
ls1
累积前n个元素,ls2
累积其余的元素。(define split-2 (lambda (ls n k) (let f ([i 1] [s ls] [k k]) (cond [(null? s) (k '() '())] [(<= i n) (f (+ i 1) (cdr s) (lambda (ls1 ls2) (k (cons (car s) ls1) ls2)))] [else (f (+ i 1) (cdr s) (lambda (ls1 ls2) (k ls1 (cons (car s) ls2))))])))) (define return (lambda (ls1 ls2) (list ls1 ls2))) (define split (lambda (ls n) (split-2 ls n return)))
CPS方式特别适合在函数中收集多个中间结果的情况,这里收集了
ls1
和ls2
。