条件表达式 #
一、条件表达式简介 #
Clojure中的条件表达式都是表达式而非语句,它们都有返回值。Clojure提供了多种条件表达式来处理不同的分支场景。
1.1 真值判断 #
在Clojure中,只有 false 和 nil 是逻辑假:
clojure
(boolean true)
(boolean false)
(boolean nil)
(boolean 0)
(boolean "")
(boolean [])
二、if表达式 #
2.1 基本语法 #
clojure
(if condition
then-expr
else-expr)
(if true
"yes"
"no")
(if false
"yes"
"no")
(if nil
"yes"
"no")
2.2 省略else #
clojure
(if true
"yes")
(if false
"yes")
省略else时,条件为假返回nil。
2.3 多表达式 #
使用 do 包装多个表达式:
clojure
(if true
(do
(println "True!")
"result")
"false result")
2.4 嵌套if #
clojure
(defn classify [n]
(if (< n 0)
"negative"
(if (= n 0)
"zero"
"positive")))
(classify -5)
(classify 0)
(classify 5)
三、when表达式 #
3.1 基本语法 #
clojure
(when condition
expr1
expr2
...)
(when true
(println "Processing...")
"done")
(when false
(println "This won't print")
"done")
3.2 when-not #
clojure
(when-not false
"not false")
(when-not true
"won't execute")
3.3 when vs if #
| 特性 | if | when |
|---|---|---|
| else分支 | 支持 | 不支持 |
| 多表达式 | 需要do | 自动支持 |
| 返回值 | 条件相关 | 条件为假返回nil |
建议:当不需要else分支时,优先使用 when。
四、cond表达式 #
4.1 基本语法 #
clojure
(cond
condition1 expr1
condition2 expr2
:else default-expr)
(defn grade [score]
(cond
(>= score 90) "A"
(>= score 80) "B"
(>= score 70) "C"
(>= score 60) "D"
:else "F"))
(grade 95)
(grade 75)
(grade 50)
4.2 :else关键字 #
clojure
(cond
false "never"
false "also never"
:else "default")
:else 不是特殊语法,只是惯用的默认分支写法。
4.3 无默认分支 #
clojure
(cond
false "a"
false "b")
(cond
false "a"
false "b"
:else nil)
五、case表达式 #
5.1 基本语法 #
clojure
(case expr
value1 result1
value2 result2
default-result)
(defn direction [d]
(case d
:north "Up"
:south "Down"
:east "Right"
:west "Left"
"Unknown"))
(direction :north)
(direction :up)
5.2 多值匹配 #
clojure
(defn classify [x]
(case x
(1 2 3) "small"
(4 5 6) "medium"
(7 8 9) "large"
"other"))
(classify 2)
(classify 5)
(classify 10)
5.3 case vs cond #
| 特性 | case | cond |
|---|---|---|
| 匹配方式 | 精确相等 | 任意条件 |
| 性能 | O(1) | O(n) |
| 编译期 | 常量 | 运行时 |
| 灵活性 | 低 | 高 |
六、if-let和when-let #
6.1 if-let #
clojure
(if-let [binding test]
then-expr
else-expr)
(defn process [x]
(if-let [value (get x :key)]
(str "Found: " value)
"Not found"))
(process {:key "hello"})
(process {:other "value"})
6.2 when-let #
clojure
(when-let [binding test]
expr1
expr2)
(defn process [x]
(when-let [value (get x :key)]
(println "Processing:" value)
(* value 2)))
(process {:key 5})
(process {:other 1})
6.3 多绑定 #
clojure
(if-let [a 1
b 2]
(+ a b)
0)
(if-let [a 1
b nil]
(+ a b)
0)
所有绑定都必须为真。
七、condp表达式 #
7.1 基本语法 #
clojure
(condp pred expr
value1 result1
value2 result2
default-result)
(defn classify [n]
(condp = n
1 "one"
2 "two"
3 "three"
"other"))
(classify 2)
(classify 5)
7.2 自定义谓词 #
clojure
(defn check [n]
(condp < n
0 "negative"
10 "small"
100 "medium"
"large"))
(check -5)
(check 5)
(check 50)
(check 500)
7.3 使用函数结果 #
clojure
(condp some [1 2 3 4 5]
#{0 6 7} :>> inc
#{4 5 9} :>> dec
#{1 2 3} :>> #(* % 10))
八、逻辑运算 #
8.1 and #
clojure
(and true true)
(and true false)
(and 1 2 3)
(and 1 nil 3)
(and)
and 返回第一个假值或最后一个值。
8.2 or #
clojure
(or false true)
(or false false)
(or nil 1 2)
(or)
or 返回第一个真值或最后一个值。
8.3 not #
clojure
(not true)
(not false)
(not nil)
(not "hello")
8.4 实用模式 #
clojure
(defn default-name [name]
(or name "Anonymous"))
(default-name "Alice")
(default-name nil)
(defn all-positive? [a b c]
(and (pos? a) (pos? b) (pos? c)))
(all-positive? 1 2 3)
(all-positive? 1 -2 3)
九、实践示例 #
9.1 输入验证 #
clojure
(defn validate-user [{:keys [name age email]}]
(cond
(empty? name)
{:error "Name is required"}
(or (nil? age) (neg? age))
{:error "Age must be a positive number"}
(and email (not (re-matches #".+@.+" email)))
{:error "Invalid email format"}
:else
{:valid true}))
(validate-user {:name "" :age 25})
(validate-user {:name "Alice" :age -1})
(validate-user {:name "Alice" :age 25 :email "invalid"})
(validate-user {:name "Alice" :age 25 :email "alice@example.com"})
9.2 状态机 #
clojure
(defn next-state [current event]
(case [current event]
[:idle :start] :running
[:running :pause] :paused
[:running :stop] :idle
[:paused :resume] :running
[:paused :stop] :idle
current))
(next-state :idle :start)
(next-state :running :pause)
(next-state :paused :resume)
9.3 配置处理 #
clojure
(defn get-config [config key]
(if-let [value (get config key)]
value
(if-let [default (get config :default)]
default
nil)))
(get-config {:a 1 :default "N/A"} :a)
(get-config {:a 1 :default "N/A"} :b)
(get-config {:a 1} :b)
9.4 权限检查 #
clojure
(defn check-access [user resource action]
(cond
(= (:role user) :admin)
true
(and (= (:role user) :user)
(contains? #{:read :list} action))
true
(and (= (:role user) :guest)
(= action :read)
(:public resource))
true
:else false))
(check-access {:role :admin} {} :delete)
(check-access {:role :user} {} :read)
(check-access {:role :guest} {:public true} :read)
(check-access {:role :guest} {:public false} :read)
十、总结 #
条件表达式速查:
| 表达式 | 用途 |
|---|---|
if |
二选一 |
when |
条件执行,无else |
cond |
多条件分支 |
case |
精确匹配 |
if-let |
绑定+判断 |
when-let |
绑定+条件执行 |
condp |
谓词匹配 |
关键点:
- 条件表达式都有返回值
- 只有
false和nil是逻辑假 when比if更简洁(无else时)case性能最好(编译期常量)if-let/when-let简化绑定判断
下一步,让我们学习循环与递归!
最后更新:2026-03-27