contrib.seq-utilsを使ってみた。
使い方のカタログ的なもの。
(use 'clojure.contrib.seq-utils)が必要。
separate
gaucheのpartitionみたいなもの。述語をひとつ取り真か偽かで仕分けする。
(def nums (take 10 (iterate inc 0))) (filter odd? nums) ; => (1 3 5 7 9) (filter (complement odd?) nums) ; => (0 2 4 6 8) (separate odd? nums) ; => [(1 3 5 7 9) (0 2 4 6 8)]
rec-seq
自身を利用した遅延sequenceを作る際に便利なマクロ。reductionsを定義するのに使われている。
(let [c [1 2 3]] (rec-seq c [10 20 30])) ; => (10 20 30) (let [c [1 2 3]] (rec-seq c (concat [10 20 30] c))) ; => (10 20 30 10 20 30 10 20 30 10 ...) (let [coll [10 1 2 3 4]] (rec-seq self (cons (first coll) (map + self (rest coll))))) ; => (10 11 13 16 20)
indexed
clojure版with-indexと考えれば良い。 (indexed (take 5 (iterate (comp char inc int) \a))) ; => ([0 \a] [1 \b] [2 \c] [3 \d] [4 \e])
partition-by
haskellのgroup関数の汎用版.どのようにgroupingするのか述語を取れる
(partition-by identity nums) ;; => ((0) (1) (2) (3) (4) (5) (6) (7) (8) (9)) (partition-by identity '(1 1 1 2 2 2 1 1 2 1 1 1 1 2 2 2)) ;; => ((1 1 1) (2 2 2) (1 1) (2) (1 1 1 1) (2 2 2))
rec-cat
lazy-catをもう少し楽に行うためのマクロ。フィボナッチ数列を楽に書ける。
(def fibs (lazy-cat [0 1] (map + fibs (next fibs)))) (rec-cat fibs [0 1] (map + fibs (next fibs)))
frequencies
集計するときに使える。自分で書いてもそんなに面倒じゃない。名前が覚えられない。
(frequencies '(1 1 1 2 2 2 1)) ; => {2 3, 1 4} (reduce #(assoc %1 %2 (inc (get %1 %2 0))) {} '(1 1 1 2 2 2 1)) ; => {2 3, 1 4}
shuffle
名前のとおり。sort-byで似非shuffleをする必要がなくなった。
(shuffle (take 10 nums)) ; => (3 0 7 1 4 9 8 5 6 2)
reductions
mapaccumに近いようなもの。この関数のソースを見るとrec-seqの使い方が分かる。
(reductions + [10 0 0 0]) ; => (10 10 10 10) (reductions + [10 1 2 3]) ; => (10 11 13 16) (reductions vector [10 1 2 3]) ; => (10 [10 1] [[10 1] 2] [[[10 1] 2] 3]) (reductions * [1 2 3 4 5]) ; => (1 2 6 24 120)
seq-on
seqのようなものmulti-methodを使うときに利用するみたい。分からない。
rotations
全てのrotationの可能性を返す
(rotations [1 2 3]) ; => ((1 2 3) (2 3 1) (3 1 2))
partition-all
partitionの末尾まで返すversion。gaucheのutil.listのslicesはこんな感じ
(partition 4 nums) ; => ((0 1 2 3) (4 5 6 7)) (partition-all 4 nums) ; => ((0 1 2 3) (4 5 6 7) (8 9))
group-by
渡した関数でgroupingしたsortedMapを返す。(partition-byはlazy-sequence)
(defn abs [x] (if (neg? x) (- x) x)) (group-by abs [-1 -2 0 1 2]) ; => {0 [0], 1 [-1 1], 2 [-2 2]}
includes?
member的なもの
(includes?(take 5 nums) 5) ; => false (includes?(take 5 nums) 3) ; => true
find-first
find-firstがよくあるプログラミングでのfind。
ソースを見て気づいたけれど、lazy-sequenceだから(comp first filter)で良いのか
((comp first filter) odd? [2 1 3 4]) ; => 1 (find-first odd? [2 1 3 4]) ; => 1
flatten
これはsourceで中を覗いてみるべき関数かもしれない。seq?ではなくsequential?を使うとか,
filter+(complement sequential?)の前にrestをつけるとか地味に気づかない。*1
rand-elt
randomに要素を選択する(重複あり)
(let [coll (range 1 5)] (map (fn [_] (rand-elt coll)) coll)) ; => (3 2 4 2)
*1:単にあまり考えていないだけだけれど