函数定义 #
一、函数基础 #
函数是Clojure的核心。作为函数式编程语言,Clojure中的函数是一等公民,可以像数据一样传递和操作。
1.1 使用defn定义函数 #
clojure
(defn greet [name]
(str "Hello, " name "!"))
(greet "World")
1.2 函数组成部分 #
clojure
(defn function-name
"Documentation string"
[parameters]
(body))
| 部分 | 说明 |
|---|---|
defn |
定义函数的宏 |
function-name |
函数名(符号) |
"doc-string" |
文档字符串(可选) |
[parameters] |
参数向量 |
(body) |
函数体表达式 |
1.3 查看文档 #
clojure
(defn square
"Returns the square of a number.
Example: (square 5) => 25"
[x]
(* x x))
(doc square)
二、参数 #
2.1 无参数函数 #
clojure
(defn pi []
3.14159)
(pi)
2.2 单参数函数 #
clojure
(defn double-it [x]
(* x 2))
(double-it 5)
2.3 多参数函数 #
clojure
(defn add [a b]
(+ a b))
(defn greet [first-name last-name]
(str "Hello, " first-name " " last-name))
(greet "John" "Doe")
2.4 可变参数 #
使用 & 收集剩余参数:
clojure
(defn sum-all [& numbers]
(apply + numbers))
(sum-all 1 2 3 4 5)
(defn greet-all [greeting & names]
(str greeting ", " (clojure.string/join ", " names)))
(greet-all "Hello" "Alice" "Bob" "Carol")
2.5 混合参数 #
clojure
(defn format-message [prefix & parts]
(str prefix ": " (clojure.string/join " " parts)))
(format-message "ERROR" "File" "not" "found")
三、多参数列表 #
Clojure支持函数重载,根据参数数量执行不同逻辑:
3.1 基本多参数列表 #
clojure
(defn greet
([name]
(greet "Hello" name))
([greeting name]
(str greeting ", " name "!")))
(greet "Alice")
(greet "Hi" "Bob")
3.2 默认参数 #
clojure
(defn make-point
([x y] (make-point x y 0))
([x y z]
{:x x :y y :z z}))
(make-point 1 2)
(make-point 1 2 3)
3.3 完整示例 #
clojure
(defn calculate
([x] (* x x))
([x y] (+ x y))
([x y z] (+ x y z)))
(calculate 5)
(calculate 3 4)
(calculate 1 2 3)
四、函数体 #
4.1 隐式do #
函数体可以包含多个表达式,返回最后一个:
clojure
(defn process [x]
(println "Processing:" x)
(let [result (* x 2)]
(println "Result:" result)
result))
(process 5)
4.2 使用let #
clojure
(defn calculate-area [width height]
(let [area (* width height)]
(str "Area: " area " square units")))
(calculate-area 5 3)
4.3 条件表达式 #
clojure
(defn absolute [x]
(if (neg? x)
(- x)
x))
(absolute -5)
(absolute 5)
五、函数元数据 #
5.1 添加元数据 #
clojure
(defn ^:private helper []
"internal helper")
(defn ^String process [s]
(str "Processed: " s))
(meta #'helper)
5.2 常用元数据 #
clojure
(defn ^:dynamic config []
{:debug true})
(defn ^:const max-value []
100)
(defn ^:deprecated old-function []
"Use new-function instead")
六、私有函数 #
6.1 defn- #
clojure
(defn- internal-helper []
"This is private")
(defn public-api []
(internal-helper))
私有函数只能在定义它的命名空间内使用。
6.2 元数据方式 #
clojure
(defn ^:private another-helper []
"Also private")
七、前置/后置条件 #
7.1 使用:pre和:post #
clojure
(defn divide [a b]
{:pre [(not= b 0)]
:post [(number? %)]}
(/ a b))
(divide 10 2)
(divide 10 0)
7.2 多个条件 #
clojure
(defn calculate-bmi [weight height]
{:pre [(pos? weight) (pos? height)]
:post [(<= 10 % 50)]}
(/ weight (* height height)))
(calculate-bmi 70 1.75)
八、函数作为值 #
8.1 函数是一等公民 #
clojure
(defn apply-twice [f x]
(f (f x)))
(apply-twice inc 5)
(apply-twice #(* % 2) 3)
8.2 返回函数 #
clojure
(defn make-adder [n]
(fn [x] (+ x n)))
(def add5 (make-adder 5))
(def add10 (make-adder 10))
(add5 3)
(add10 3)
8.3 函数组合 #
clojure
(defn compose [f g]
(fn [x]
(f (g x))))
(def add1-then-double (compose #(* % 2) inc))
(add1-then-double 4)
(comp inc #(* % 2))
九、常用函数 #
9.1 apply #
clojure
(apply + [1 2 3 4 5])
(apply + 1 2 [3 4 5])
(apply str ["a" "b" "c"])
9.2 partial #
clojure
(def add5 (partial + 5))
(add5 3)
(def greet-hello (partial str "Hello, "))
(greet-hello "World")
9.3 comp #
clojure
(def inc-then-double (comp #(* % 2) inc))
(inc-then-double 4)
(def process (comp str/upper-case str/reverse))
(process "hello")
9.4 complement #
clojure
(def not-empty? (complement empty?))
(not-empty? [])
(not-empty? [1 2 3])
9.5 constantly #
clojure
(def always-5 (constantly 5))
(always-5)
(always-5 1 2 3)
9.6 identity #
clojure
(identity 42)
(filter identity [1 nil 2 nil 3])
十、实践示例 #
10.1 构建器模式 #
clojure
(defn make-person
([name] (make-person name nil nil))
([name age] (make-person name age nil))
([name age email]
(cond-> {:name name}
age (assoc :age age)
email (assoc :email email))))
(make-person "Alice")
(make-person "Bob" 30)
(make-person "Carol" 25 "carol@example.com")
10.2 策略模式 #
clojure
(defn calculate [strategy a b]
(strategy a b))
(defn add [a b] (+ a b))
(defn multiply [a b] (* a b))
(defn subtract [a b] (- a b))
(calculate add 5 3)
(calculate multiply 5 3)
(calculate subtract 5 3)
10.3 装饰器模式 #
clojure
(defn with-logging [f]
(fn [& args]
(println "Calling with args:" args)
(let [result (apply f args)]
(println "Result:" result)
result)))
(defn add [a b]
(+ a b))
(def logged-add (with-logging add))
(logged-add 3 4)
十一、总结 #
函数定义要点:
| 特性 | 语法 |
|---|---|
| 基本定义 | (defn name [params] body) |
| 文档字符串 | (defn name "doc" [params] body) |
| 可变参数 | (defn name [x & rest] body) |
| 多参数列表 | (defn name ([x] ...) ([x y] ...)) |
| 私有函数 | (defn- name ...) |
关键点:
- 函数是一等公民
- 支持多参数列表重载
- 可变参数使用
& - 元数据控制可见性和行为
- 前置/后置条件验证
下一步,让我们学习高阶函数!
最后更新:2026-03-27