这里出现了 TLS 的第三要点 When building a list, describe the first typical element, and then cons it onto the natural recursion 总的来说就是寻找一个可以迭代的过程, 然后利用它递归的填充list。 这回到了前文 lat 的讨论, 其实和前面的解决方法是一样的, 寻找递归过程,然后组合起来。
补充
后文非原文内容
insertR
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
(def insertR " It takes three arguments: the atoms new and old, and a lat. The function insertR builds a lat with new inserted to the right of the first occurrence of old " (fn [new old lat] (cond ;(null? lat) (seq []) (null? lat) '() ;(= old (first lat)) (cons (cons (first lat) new) (rest lat)) (= old (first lat)) (cons old (cons new (rest lat))) :else (cons (first lat) (insertR new old (rest lat))))))
(insertR 2 1 '(1 3 4 1 3))
insertL
1 2 3 4 5 6 7 8 9 10
(def insertL (fn [new old lat] (cond (null? lat) (seq []) (= old (first lat)) (cons new lat) :else (cons (first lat) (insertL new old (rest lat))))))
(insertL23 '(134))
subst
1 2 3 4 5 6 7 8 9 10 11 12 13
(def subst " replaces the first occurrence of old in the lat with new " (fn [new old lat] (cond (null? lat) (seq []) (= old (first lat)) (cons new (rest lat)) :else (cons (first lat) (subst new old (rest lat))))))
(subst 10 2 '(1 2 3))
subst2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
(def subst2 " replaces either the first occurrence of o1 or the first occurrence of o2 by new " (fn [new o1 o2 lat] (cond (null? lat) (seq []) :else (cond ;(= (first lat) o1) (cons new (rest lat)) ;(= (first lat) o2) (cons new (rest lat)) (or (= (first lat) o1) (= (first lat) o2)) (cons new (rest lat)) :else (cons (first lat) (subst2 new o1 o2 (rest lat)))))))
(subst2 0 1 2 '(1 2 3 4))
后面的函数都是前面的multi 版本
multi的是对非multi的得到的结果再进行迭代(直到 (null? lat))
multirember
1 2 3 4 5 6 7 8 9 10 11 12 13
(def multirember " gives as its final value the lat with all occurrences of a removed. " (fn [a lat] (cond (null? lat) '() :else (cond (= a (first lat)) (multirember a (rest lat)) :else (cons (first lat) (multirember a (rest lat)))))))
(multirember 3 '(1 2 3 4 3 5))
1 2 3 4 5 6 7 8 9 10 11 12 13 14
(def multiinsertR " remove multi old " (fn [new old lat] (cond (null? lat) '() :else (cond (= old (first lat)) (cons old (cons new (multiinsertR new old (rest lat)))) :else (cons (first lat) (multiinsertR new old (rest lat)))))))
(multiinsertR 0 3 '(1 2 3 4 5 3 6))
1 2 3 4 5 6 7 8 9 10 11 12
(def multiinsertL (fn [new old lat] (cond (null? lat) '() :else (cond (= old (first lat)) ;; 这里如果写成 (cons new (multiinsertL new old lat)) stackOverflow 仔细想想 (cons new (cons old (multiinsertL new old (rest lat)))) :else (cons (first lat) (multiinsertL new old (rest lat)))))))
(multiinsertL03 '(1234536))
上文第一次我就写成了 (multiinsertL new old lat) 这就导致,一旦满足 (= old (first lat)) 就无限递归了。因为 lat 不会因为递归的深度加深而变小
第四戒律
Always change at least one argument while recurring. It must be changed to be closer to termination. The changing argument must be tested in the termination condition: when using cdr, test termination with null?
(defn remove "Returns a lazy sequence of the items in coll for which (pred item) returns false. pred must be free of side-effects." {:added "1.0" :static true} [pred coll] (filter (complement pred) coll))