Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

入門Transducers

Clojure 1.7勉強会の発表資料です。

入門Transducers

  1. 1. 入門Transducers Clojure 1.7勉強会 @athos0220
  2. 2. Transducerとは?
  3. 3. Transducers are composable algorithmic transformations. They are independent from the context of their input and output sources and specify only the essence of the transformation in terms of an individual element. Because transducers are decoupled from input or output sources, they can be used in many different processes - collections, streams, channels, observables, etc. http://clojure.org/transducers
  4. 4. なるほど分からん
  5. 5. つまり、、、 Transducerは合成可能なアルゴリズム的変換 入力源や出力先に依らず、各要素を変換する
  6. 6. …やっぱり分からん
  7. 7. Transducerが生まれた 経緯を知ると理解が深まる
  8. 8. Transducerが生まれた 経緯を知ると理解が深まる …かも?
  9. 9. おさらい:シーケンス処理
  10. 10. (->> (range 5) (map inc) (filter odd?) (reduce + 0))
  11. 11. (->> (range 5) (map inc) (filter odd?) (reduce + 0))
  12. 12. (->> (range 5) (map inc) (filter odd?) (reduce + 0))
  13. 13. (->> (range 5) (map inc) (filter odd?) (reduce + 0)) 各要素に1を足し
  14. 14. (->> (range 5) (map inc) (filter odd?) (reduce + 0)) 各要素に1を足し 奇数以外を取り除き
  15. 15. (->> (range 5) (map inc) (filter odd?) (reduce + 0)) 各要素に1を足し 奇数以外を取り除き 足し合わせる
  16. 16. 0 1 2 3 4(range 5)
  17. 17. 0 1 2 3 4 51 2 3 4 (range 5) (map inc) inc inc inc inc inc
  18. 18. 0 1 2 3 4 51 2 3 4 51 3 (range 5) (map inc) (filter odd?) inc inc inc inc inc odd? odd? odd? odd? odd?
  19. 19. 0 1 2 3 4 51 2 3 4 51 3 (range 5) (map inc) (filter odd?) 9 inc inc inc inc inc odd? odd? odd? odd? odd? (reduce + 0) ++ +
  20. 20. おさらい:Reducers
  21. 21. (->> (range 5) (r/map inc) (r/filter odd?) (reduce + 0))
  22. 22. (range 5) 0 1 2 3 4
  23. 23. (range 5) (r/map inc) 0 要素に1足して処理 1 2 3 4 0 1 2 3 4 Reducible
  24. 24. (range 5) (r/map inc) (r/filter odd?) 0 要素に1足して処理 1 2 3 4 0 1 2 3 4 0 要素に1足して処理 奇数ならば処理 1 2 3 4 Reducible Reducible
  25. 25. (range 5) (r/map inc) (r/filter odd?) (reduce + 0) 0 要素に1足して処理 1 2 3 4 0 1 2 3 4 9 0 要素に1足して処理 奇数ならば処理 1 2 3 4 要素に1足して処理 奇数ならば処理 + Reducible Reducible
  26. 26. おさらい:Reducers Reducerでは、シーケンス処理と異なり、各 ステップで要素毎の中間データを作らない reduceする段階で各要素に処理を適用する (本来はさらにfork/joinを使った並列処理に発展するけどここでは割愛)
  27. 27. で、     って 具体的に何? 要素に1足して処理
  28. 28. (reduce + 0 (map inc s))
  29. 29. (reduce + 0 (map inc s))
  30. 30. (reduce + 0 (map inc s))
  31. 31. (reduce + 0 (map inc s)) 「各要素を1足して、 先頭から順に要素を足し合わせる」
  32. 32. (reduce + 0 (map inc s)) 「各要素を1足して、 先頭から順に要素を足し合わせる」 (reduce (fn [a x] (+ a (inc x))) 0 s) 「先頭から順に各要素に1足した値を足し合わせる」 これは以下と等価
  33. 33. (reduce (fn [a x] (+ a (inc x))) 0 s)
  34. 34. (reduce (fn [a x] (+ a (inc x))) 0 s)(fn [a x] (+ a (inc x)))
  35. 35. これが      の正体要素に1足して処理 (fn [a x] (+ a (inc x)))
  36. 36. 同じように
  37. 37. (reduce + 0 (filter odd? s))
  38. 38. (reduce + 0 (filter odd? s))
  39. 39. (reduce + 0 (filter odd? s))
  40. 40. (reduce + 0 (filter odd? s)) 「奇数以外の要素を取り除き、 先頭から順に要素を足し合わせる」
  41. 41. (reduce + 0 (filter odd? s)) 「奇数以外の要素を取り除き、 先頭から順に要素を足し合わせる」 (reduce (fn [a x] (if (odd? x) (+ a x) a)) 0 s) 「先頭から順に奇数の要素を足し合わせる」 これは以下と等価
  42. 42. (reduce (fn [a x] (if (odd? x) (+ a x) a)) 0 s)
  43. 43. (reduce (fn [a x] (if (odd? x) (+ a x) a)) 0 s) (fn [a x] (if (odd? x) (+ a x) a))
  44. 44. これが      の正体奇数ならば処理 (fn [a x] (if (odd? x) (+ a x) a))
  45. 45. 一般的に (reduce op z (map f s)) (reduce (fn [a x] (op a (f x))) z s) =
  46. 46. 一般的に (reduce op z (filter f s)) (reduce (fn [a x] (if (f x) (op a x) a) z s) =
  47. 47. これらは各シーケンス処理の 本質的な部分を表すものとして 標準の関数から取得できるようになった (map f) = (fn [op] (fn [a x] (op a (f x))) (filter f) = (fn [op] (fn [a x] (if (f x) (op a x) a)))
  48. 48. これらは各シーケンス処理の 本質的な部分を表すものとして 標準の関数から取得できるようになった (map f) = (fn [op] (fn [a x] (op a (f x))) (filter f) = (fn [op] (fn [a x] (if (f x) (op a x) a))) ↑これがTransducer!!
  49. 49. = (map inc)要素に1足して処理 奇数ならば処理 = (filter odd?)
  50. 50. Transducerの実体はただの関数なので 関数合成により合成できる 要素に1足して処理 奇数ならば処理 + 要素に1足して処理 奇数ならば処理 (comp (map inc) (filter odd?)) 合成したものもTransducer
  51. 51. 0 要素に1足して処理 奇数ならば処理 1 2 3 4 Reducible
  52. 52. 0 要素に1足して処理 奇数ならば処理 1 2 3 4 Reducible Reducible = Transducer + コレクション
  53. 53. 0 要素に1足して処理 奇数ならば処理 1 2 3 4 Reducible Reducible = Transducer + コレクション 逆に、Transducerとは Reducibleからコレクションへの依存を除き 汎用的に使えるようにしたものといえる
  54. 54. さまざまなTransducer 多くの標準シーケンス処理関数が1.7以降Transducer を返すようになる map mapcat filter remove take take-while drop drop-while take-nth replace partition-by partition-all keep keep-indexed map-indexed distinct interpose
  55. 55. Transducerを使うときの注意点 関数合成の順序が通常と逆になる 内部状態をもつTransducerがあるため、 Transducerは使い回さない
  56. 56. Transducerを引数にとるAPI (transduce xf f init s) = (reduce (xf f) init s) (into to xf from) コレクションfromをtransducerで変換しながらコレ クションtoに変換 (eduction xf coll) transducerとコレクションからReducibleを生成
  57. 57. core.asyncでの利用 (def c (async/chan (comp (map inc) (filter odd?)))) (async/onto-chan c (range 5)) (async/<!! c) ;=> 1 (async/<!! c) ;=> 3 (async/<!! c) ;=> 5 対象のデータ構造に依らないためチャネルからも使える
  58. 58. まとめ Transducerは対象とするデータ構造に依らな いアルゴリズム的変換を記述する標準的な方法 中間データを生成しないため、従来のシーケン ス処理よりも高速化できる可能性も

×