高阶函数 #
一、高阶函数简介 #
高阶函数是指接受函数作为参数或返回函数的函数。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 |
存在满足 |
关键点:
- 高阶函数是函数式编程核心
map、filter、reduce三剑客->和->>简化链式调用- Transducers 提供可组合、高效的转换
下一步,让我们学习匿名函数!
最后更新:2026-03-27