Clojure 编程学习笔记

1. 变量与常量

Clojure 中的变量不可变,使用 def 声明符号绑定。

(def name "Alice")
(def age 30)

注意事项:变量默认不可变,避免误修改。

2. 数据类型

Clojure 支持基本数据类型如 numberstringbooleankeyword

(def height 1.75)
(def is-student true)
(def city "New York")

易错点:关键词使用 : 定义,适用于标签和标识。

3. 条件表达式

Clojure 使用 ifwhencond 实现条件控制。

(if (> age 18)
    "Adult"
    "Minor")

注意事项: if 表达式必须有一个 else 分支。

4. 函数

函数使用 defn 定义,匿名函数使用 fn

(defn greet [name]
  (str "Hello, " name))

易错点: Clojure 函数参数使用方括号传递,确保参数匹配。

5. 集合操作

Clojure 提供丰富的集合操作,支持 listvectorsetmap

(def names ["Alice" "Bob"])
(def scores {:Alice 90 :Bob 85})

注意事项:集合是不可变的,操作集合返回新集合。

6. 惰性求值

Clojure 的惰性求值允许构建无限序列。

(def infinite-nums (iterate inc 0))

注意事项:使用 take 等函数防止无限求值。

7. 递归

Clojure 使用递归来处理循环,通过 recur 实现尾递归。

(defn factorial [n]
  (if (<= n 1)
    1
    (* n (factorial (dec n)))))

易错点: recur 必须在尾调用位置,以实现优化。

8. 宏

宏用于生成代码,类似于元编程。

(defmacro unless [cond body]
  `(if (not ~cond)
     ~body))

注意事项:宏参数需使用 ~ 进行解引用。

9. 并发编程

Clojure 支持并发,使用 futurepromise 创建并发任务。

(def task (future (println "Running concurrently!")))

注意事项:通过 @ 获取并发结果。

高级与小众用法

惰性序列

Clojure 支持惰性序列,按需计算,节省内存。

(take 5 (range))

注意事项:无限序列需使用 takedrop 控制。

高阶函数

Clojure 提供了丰富的高阶函数,如 mapfilterreduce

(map inc [1 2 3])  ; => (2 3 4)

易错点:高阶函数处理集合时,避免未定义函数。

关键字参数

关键字参数允许函数更灵活地传递可选参数。

(defn greet [& {:keys [name age]}]
  (str "Hello, " name ", age " age))

注意事项:使用 :keys 解构关键字参数。

Ref 与 Atom

使用 refatom 管理状态,支持原子操作。

(def count (atom 0))
(swap! count inc)

注意事项: swap! 使用安全的原子操作更新状态。

多方法

Clojure 支持多方法,基于不同参数调用不同方法。

(defmulti greet :type)
(defmethod greet :formal [_] "Good day!")
(defmethod greet :informal [_] "Hey!")

注意事项:使用 defmulti 定义分派规则,defmethod 实现分支方法。

解构

Clojure 支持函数参数解构,简化数据访问。

(defn display-person [{:keys [name age]}]
  (str name " is " age " years old"))

易错点:使用 :keys:as 解构复杂数据结构。