Skip to content

第 10 章: 高階関数と関数合成

10.1 はじめに

この章では Clojure の 高階関数関数合成 を使って、FizzBuzz プログラムをより関数型らしいスタイルに変換します。

10.2 高階関数

高階関数とは、関数を引数として受け取るか、関数を返す関数のことです。Clojure では関数がファーストクラスの値であり、変数に束縛したり、引数として渡したりできます。

map / filter / reduce

;; map: 各要素に関数を適用
(map fizzbuzz (range 1 16))
;=> ("1" "2" "Fizz" "4" "Buzz" "Fizz" "7" "8" "Fizz" "Buzz"
;    "11" "Fizz" "13" "14" "FizzBuzz")

;; filter: 条件を満たす要素のみ抽出
(filter #(not= "" %) (map #(type/generate-string (type/->FizzBuzzType03)
                                                  (model/create-fizz-buzz-value %))
                          (range 1 16)))
;=> ("Fizz" "Buzz" "Fizz" "Fizz" "Buzz" "Fizz" "FizzBuzz")

;; reduce: 累積処理
(reduce str (map fizzbuzz (range 1 6)))
;=> "12FizzBuzz4"

部分適用(partial)

partial は関数の一部の引数を固定して新しい関数を作ります。

(def fizzbuzz-type1
  (partial type/generate-string (type/->FizzBuzzType01)))

(fizzbuzz-type1 (model/create-fizz-buzz-value 15))
;=> "FizzBuzz"

無名関数

;; fn による無名関数
(map (fn [n] (fizzbuzz n)) (range 1 6))

;; #() リーダーマクロによる短縮形
(map #(fizzbuzz %) (range 1 6))

10.3 関数合成

comp による関数合成

comp は複数の関数を合成して新しい関数を作ります。右から左へ適用されます。

(def fizzbuzz-with-prefix
  (comp (partial str "=> ") fizzbuzz))

(fizzbuzz-with-prefix 3)
;=> "=> Fizz"

(fizzbuzz-with-prefix 15)
;=> "=> FizzBuzz"

スレッディングマクロ

->->> はデータの変換パイプラインを記述します。

;; ->> マクロ(最後の引数に挿入)
(->> (range 1 101)
     (map fizzbuzz)
     (filter #(re-matches #"[A-Za-z]+" %))
     (take 5))
;=> ("Fizz" "Buzz" "Fizz" "Fizz" "Buzz")

;; -> マクロ(最初の引数に挿入)
(-> 15
    fizzbuzz
    clojure.string/upper-case)
;=> "FIZZBUZZ"

10.4 関数ファクトリ

関数を返す関数を使って、カスタマイズ可能な処理を作れます。

(defn create-fizzbuzz-filter
  "指定パターンにマッチする FizzBuzz 結果をフィルタリングする関数を返す"
  [pattern]
  (fn [results]
    (filter #(clojure.string/includes? % pattern) results)))

(def fizz-filter (create-fizzbuzz-filter "Fizz"))
(def buzz-filter (create-fizzbuzz-filter "Buzz"))

(fizz-filter ["1" "Fizz" "Buzz" "FizzBuzz"])
;=> ("Fizz" "FizzBuzz")

10.5 まとめ

この章では以下のことを学びました。

  • map / filter / reduce による高階関数の活用
  • partial による部分適用
  • comp による関数合成
  • スレッディングマクロ->->>)によるパイプライン処理
  • 関数ファクトリ(関数を返す関数)パターン