1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Clojureの高階関数について

1
Last updated at Posted at 2025-06-24

高階関数とは

高階関数とは、関数を引数として受け取るか、関数を戻り値として返す関数のことです。Clojureでは関数が第一級オブジェクトなので、高階関数を自然に扱えます。

基本的な高階関数

map - コレクションの各要素に関数を適用

;; 基本的な使い方
(map inc [1 2 3 4 5])
;; => (2 3 4 5 6)

;; 複数のコレクションに対して
(map + [1 2 3] [4 5 6])
;; => (5 7 9)

;; 文字列の操作
(map clojure.string/upper-case ["hello" "world"])
;; => ("HELLO" "WORLD")

filter - 条件に合う要素のみを抽出

;; 偶数のみを抽出
(filter even? [1 2 3 4 5 6])
;; => (2 4 6)

;; 文字列の長さで絞り込み
(filter #(> (count %) 3) ["cat" "dog" "elephant" "ant"])
;; => ("elephant")

reduce - コレクションを1つの値に集約

;; 合計を計算
(reduce + [1 2 3 4 5])
;; => 15

;; 最大値を求める
(reduce max [3 7 2 9 1])
;; => 9

;; 初期値を指定
(reduce + 100 [1 2 3])
;; => 106

無名関数(ラムダ関数)

fn記法

;; 基本的なfn記法
((fn [x] (* x x)) 5)
;; => 25

;; mapと組み合わせ
(map (fn [x] (* x x)) [1 2 3 4])
;; => (1 4 9 16)

;; 複数引数の無名関数
(map (fn [x y] (+ (* x x) (* y y))) [1 2 3] [4 5 6])
;; => (17 29 45)

#()記法

;; シンプルな場合
(#(* % %) 5)
;; => 25

;; mapと組み合わせ
(map #(* % %) [1 2 3 4])
;; => (1 4 9 16)

;; 複数引数(%1, %2, %3...)
(map #(+ (* %1 %1) (* %2 %2)) [1 2 3] [4 5 6])
;; => (17 29 45)

;; ネストした場合(読みにくい例)
(map #(map #(* % %) %) [[1 2] [3 4] [5 6]])
;; => ((1 4) (9 16) (25 36))

その他

過度にネストした括弧

;; 醜い書き方
(reduce + (map #(* % %) (filter even? (range 1 11))))
;; => 220

;; 読みやすい書き方(->>マクロ使用)
(->> (range 1 11)
     (filter even?)
     (map #(* % %))
     (reduce +))
;; => 220

関数を返す関数

;; 乗数を固定した関数を生成
(defn multiplier [n]
  (fn [x] (* n x)))

(def double (multiplier 2))
(def triple (multiplier 3))

(double 5)   ;; => 10
(triple 4)   ;; => 12

;; mapと組み合わせ
(map (multiplier 10) [1 2 3])
;; => (10 20 30)

部分適用とカリー化

;; partialを使った部分適用
(def add-10 (partial + 10))

(add-10 5)   ;; => 15
(map add-10 [1 2 3 4])
;; => (11 12 13 14)

;; より複雑な例
(def starts-with-a? (partial re-matches #"^[aA].*"))

(filter starts-with-a? ["apple" "banana" "avocado" "cherry"])
;; => ("apple" "avocado")

データ処理パイプライン

(def sales-data
  [{:name "Alice" :sales 1200 :region "East"}
   {:name "Bob" :sales 800 :region "West"}
   {:name "Charlie" :sales 1500 :region "East"}
   {:name "Diana" :sales 900 :region "West"}])

;; East地域の売上合計
(->> sales-data
     (filter #(= (:region %) "East"))
     (map :sales)
     (reduce +))
;; => 2700

;; 各地域の平均売上
(->> sales-data
     (group-by :region)
     (map (fn [[region people]]
            [region (/ (reduce + (map :sales people))
                      (count people))]))
     (into {}))
;; => {"East" 1350, "West" 850}

まとめ

高階関数は Clojure の強力な機能の一つです。適切に使用することで、コードの再利用性と表現力が大幅に向上します。ただし、可読性を犠牲にしないよう注意が必要です。

重要なポイント:

  • 無名関数は適度に使用し、複雑になったら名前付き関数に分離する
  • スレッディングマクロ(->->>)を活用して読みやすくする
  • #() 記法は単純な場合のみ使用し、複雑な場合は fn を使う
  • 関数合成や部分適用を活用してコードの表現力を高める
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?