高阶函数 #

一、高阶函数简介 #

高阶函数是指接受函数作为参数或返回函数的函数。Clojure提供了丰富的高阶函数,是函数式编程的核心工具。

1.1 函数作为参数 #

clojure
(map inc [1 2 3 4 5])

(filter even? [1 2 3 4 5 6])

(reduce + [1 2 3 4 5])

1.2 返回函数 #

clojure
(defn make-multiplier [n]
  (fn [x] (* n x)))

(def triple (make-multiplier 3))

(triple 5)

二、map #

2.1 基本用法 #

clojure
(map inc [1 2 3 4 5])

(map #(* % %) [1 2 3 4 5])

(map str [1 2 3])

2.2 多集合映射 #

clojure
(map + [1 2 3] [10 20 30])

(map vector [1 2 3] [:a :b :c])

(map str ["a" "b" "c"] [1 2 3])

2.3 映射Map #

clojure
(map (fn [[k v]] [k (* v 2)]) {:a 1 :b 2 :c 3})

(map-keys str {:a 1 :b 2})

(map-vals inc {:a 1 :b 2})

2.4 map-indexed #

clojure
(map-indexed vector [:a :b :c])

(map-indexed (fn [i v] [i (* v 2)]) [1 2 3 4])

2.5 mapcat #

clojure
(mapcat reverse [[1 2 3] [4 5 6]])

(mapcat (fn [x] [x x]) [1 2 3])

三、filter #

3.1 基本用法 #

clojure
(filter even? [1 2 3 4 5 6])

(filter #(< % 4) [1 2 3 4 5 6])

(filter string? [1 "a" 2 "b" 3 "c"])

3.2 remove #

clojure
(remove even? [1 2 3 4 5 6])

(remove nil? [1 nil 2 nil 3])

3.3 filterv #

clojure
(filterv even? [1 2 3 4 5 6])

3.4 keep #

clojure
(keep #(when (even? %) (* % 2)) [1 2 3 4 5])

(keep :a [{:a 1} {:b 2} {:a 3}])

3.5 keep-indexed #

clojure
(keep-indexed (fn [i v] (when (even? i) v)) [:a :b :c :d])

四、reduce #

4.1 基本用法 #

clojure
(reduce + [1 2 3 4 5])

(reduce * [1 2 3 4 5])

(reduce str ["a" "b" "c"])

4.2 带初始值 #

clojure
(reduce + 0 [1 2 3 4 5])

(reduce + 100 [1 2 3])

(reduce conj [] [1 2 3])

4.3 构建数据结构 #

clojure
(reduce (fn [m [k v]]
          (assoc m k v))
        {}
        [[:a 1] [:b 2] [:c 3]])

(reduce (fn [s x]
          (conj s x))
        #{}
        [1 2 3 2 1])

4.4 reduce-kv #

clojure
(reduce-kv (fn [m k v]
             (assoc m k (* v 2)))
           {}
           {:a 1 :b 2 :c 3})

4.5 reductions #

clojure
(reductions + [1 2 3 4 5])

(reductions conj [] [1 2 3])

五、函数组合 #

5.1 comp #

clojure
(def process (comp str/upper-case str/reverse))

(process "hello")

(def calculate (comp inc #(* % 2)))

(calculate 5)

5.2 多函数组合 #

clojure
(def pipeline
  (comp
    (partial map inc)
    (partial filter even?)
    (partial reduce +)))

(pipeline [1 2 3 4 5])

5.3 thread-first (->) #

clojure
(-> "hello"
    str/upper-case
    str/reverse)

(-> {:a {:b {:c 1}}}
    :a
    :b
    :c)

5.4 thread-last (->>) #

clojure
(->> [1 2 3 4 5]
     (map inc)
     (filter even?)
     (reduce +))

(->> "hello world"
     (str/split #" ")
     (map str/upper-case)
     (str/join "-"))

5.5 some-> 和 some->> #

clojure
(some-> {:a {:b 1}}
        :a
        :b
        inc)

(some-> {:a {:b 1}}
        :a
        :c
        inc)

5.6 cond-> 和 cond->> #

clojure
(defn process [x opts]
  (cond-> x
    (:double opts) (* 2)
    (:add-one opts) inc
    (:negate opts) -))

(process 5 {:double true :add-one true})

六、其他高阶函数 #

6.1 every? #

clojure
(every? even? [2 4 6 8])

(every? pos? [1 2 3])

(every? string? ["a" "b" "c"])

6.2 some #

clojure
(some even? [1 3 5 6 7])

(some #{:a :b} [:c :d :a :e])

(some #(when (even? %) (* % 2)) [1 3 5 6 7])

6.3 not-every? #

clojure
(not-every? even? [1 2 3 4 5])

6.4 not-any? #

clojure
(not-any? neg? [1 2 3 4 5])

(not-any? nil? [1 2 3])

6.5 iterate #

clojure
(take 5 (iterate inc 0))

(take 10 (iterate #(* % 2) 1))

6.6 repeatedly #

clojure
(take 5 (repeatedly rand))

(take 3 (repeatedly #(rand-int 100)))

6.7 cycle #

clojure
(take 10 (cycle [1 2 3]))

6.8 repeat #

clojure
(take 5 (repeat :x))

(repeat 3 "hello")

七、Transducers #

7.1 什么是Transducer #

Transducer是可组合的算法转换,独立于上下文:

clojure
(def xform
  (comp
    (map inc)
    (filter even?)
    (take 5)))

7.2 使用Transducer #

clojure
(def xform
  (comp
    (map inc)
    (filter even?)))

(sequence xform [1 2 3 4 5 6 7 8])

(into [] xform [1 2 3 4 5 6 7 8])

(transduce xform + 0 [1 2 3 4 5 6 7 8])

7.3 Transducer优势 #

  • 可组合
  • 高效(单次遍历)
  • 上下文无关
clojure
(def xform
  (comp
    (map #(* % %))
    (filter even?)
    (take 3)))

(sequence xform (range 10))

(into [] xform (range 10))

八、实践示例 #

8.1 数据管道 #

clojure
(defn process-users [users]
  (->> users
       (filter #(> (:age %) 18))
       (map #(select-keys % [:name :email]))
       (sort-by :name)
       (take 10)))

(process-users
  [{:name "Bob" :age 20 :email "bob@example.com"}
   {:name "Alice" :age 25 :email "alice@example.com"}
   {:name "Charlie" :age 15 :email "charlie@example.com"}])

8.2 词频统计 #

clojure
(defn word-frequency [text]
  (->> text
       (str/lower-case)
       (re-seq #"\w+")
       (frequencies)
       (sort-by val >)
       (take 10)))

(word-frequency "Hello world hello Clojure world world")

8.3 分组处理 #

clojure
(defn group-by-category [items]
  (->> items
       (group-by :category)
       (map (fn [[k v]] {:category k :count (count v) :items v}))
       (sort-by :count >)))

(group-by-category
  [{:name "A" :category :x}
   {:name "B" :category :y}
   {:name "C" :category :x}])

8.4 树形结构处理 #

clojure
(defn tree-map [f tree]
  (if (coll? tree)
    (map #(tree-map f %) tree)
    (f tree)))

(tree-map inc [1 [2 3] [[4 5] 6]])

九、总结 #

高阶函数速查:

函数 用途
map 映射转换
filter 过滤
reduce 归约
comp 函数组合
partial 部分应用
every? 全部满足
some 存在满足

关键点:

  1. 高阶函数是函数式编程核心
  2. mapfilterreduce 三剑客
  3. ->->> 简化链式调用
  4. Transducers 提供可组合、高效的转换

下一步,让我们学习匿名函数!

最后更新:2026-03-27