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:単にあまり考えていないだけだけれど