実装のバリエーションとして、メモ。
http://groups.google.com/group/clojure/browse_thread/thread/4072804251bbad81/15268e2a22418b8e?lnk=gst&q=flatten#15268e2a22418b8e
(defn flatten [lst] (lazy-seq (if (empty? lst) lst (let [[x & xs] lst] (if (list? x) (concat (flatten x) (flatten xs)) (cons x (flatten xs)))))))
(defn flatten-2 [lst] (lazy-seq (if-let [x (first lst)] (let [xs (rest lst)] (if (seq? x) (concat (flatten-2 x) (flatten-2 xs)) (cons x (flatten-2 xs)))))))
(defn flatten-3 [s] (lazy-seq (when-let [s (seq s)] (let [fst (first s)] (if (seq? fst) (concat (flatten-3 fst) (flatten-3 (rest s))) (cons fst (flatten-3 (rest s))))))))
user=> (flatten '(:a (:b :c) false :d :e)) (:a :b :c false :d :e) user=> (flatten-2 '(:a (:b :c) false :d :e)) (:a :b :c) user=> (flatten-3 '(:a (:b :c) false :d :e)) (:a :b :c false :d :e)
flatten-2はこの場合うまくいかない。
もちろんclojure-contribにはflattenがあるのでいちいち実装する必要はない。
user=> (use '[clojure.contrib.seq-utils :only (flatten)]) nil user=> (flatten '(:a (:b :c) false :d :e)) (:a :b :c false :d :e)
ちなみに、On Lisp版はこうなってるらしい。
(defun flatten (x) (labels ((rec (x acc) (cond ((null x) acc) ((atom x) (cons x acc)) (t (rec (car x) (rec (cdr x) acc)))))) (rec x nil)))