Skip to content

AHABHGK

Clojure

Lisp on JVM

动态类型

并发:事务内存、代理

前缀表达式

1(mod 5 / 4) ;; 1
2(+ 1 1 1 1) ;; 4
3(/ 8 2 2) ;; 2
4(< 1 2 4) ;; true
5(< 1 4 3) ;; false

字符串和字符

1(str "one: " 1 ", two: " 2) ;; "one: 1, two: 2"

布尔

1(if 0 (println "true")) ;; "true"
2(if "" (println "true")) ;; "true"
3(if nil (println "true") (println "false")) ;; "false"

列表

1(list 1 2 3)
2'(1 2 3) ;; 引用
3(first '(1 2 3)) ;; 1
4(last '(1 2 3)) ;; 3
5(rest '(1 2 3)) ;; (2 3)
6(cons :droid '(:r2d2 :c3po)) ;; (:droid :r2d2 :c3po)

向量,与列表不同在于随机访问优化

1(first [:hutt :wookie :ewok]) ;; :hutt
2(nth [:hutt :wookie :ewok] 2) ;; :ewok
3([:hutt :wookie :ewok] 2) ;; :ewok
4(last [:hutt :wookie :ewok]) ;; :ewok
5(rest [:hutt :wookie :ewok]) ;; (:wookie :ewok)
6(concat [:hutt] [:wookie]) ;; (:hutt :wookie)

集合

1(def nums #{1 2 3}) ;; #{1 3 2}
2(sort nums) ;; (1 2 3)
3(clojure.set/union nums #{4}) ;; #{1 4 2 3}
4(clojure.set/difference nums #{3 4}) ;; #{1 2}
5(nums 2) ;; 2
6(nums 4) ;; nil

映射

1(def person {:name "ahabhgk", :age 19})
2(person :name) ;; "ahabhgk"
3(merge person {:say "Hi"}) ;; {:name "ahabhgk", :age 19, :say "Hi"}
4(assoc person :say "Hi") ;; {:name "ahabhgk", :age 19, :say "Hi"}
5person ;; {:name "ahabhgk", :age 19}

函数

1(defn do-it [what] (str "use the " what))
2(do-it "force") ;; "use the force"
3
4;; doc
5(defn do-it
6 "do something"
7 [what]
8 (str "use the " what))
9
10(doc do-it)
11;; ([what])
12;; do something
13;; nil

绑定

1(defn get-age [{age :age}] age)
2(get-age person) ;; 19
3
4;; let 简化
5(let [{age :age} person] (str "the person is " age " years old")) ;; "the person is 19 years old"
6(let [[_ _ three] [1 2 3]] three) ;; 3

匿名函数

1(map (fn [w] (count w)) ["hgk" "lj"]) ;; 3 2
2(map #(count %) ["hgk" "lj"])) ;; 3 2
3
4(apply + [1 2 3]) ;; 6
5(apply max [1 2 3]) ;; 3
6
7(filter odd? [1 2 3]) ;; (1 3)
8(filter #(< % 3) [1 2 3]) ;; (1 2)

尾递归需要 loop recur

延迟计算

defrecord defprotocol

宏:将代码当作列表来处理,如果不想立即执行,就把它引起来

1(defn unless [test body] (if (not test) body))
2(unless true (println "nonono")) ;; nonono 参数立即执行
3
4(macroexpand '#(count %))
5;; (fn* [p1__2085#] (count p1__2085#)) 宏展开,查看定义的宏,前面要加 ' ,注释 ;、引用 '、匿名函数 # 都是宏
6
7(defmacro unless [test body]
8 (list 'if (list 'not test) body))
9(unless true (println "nonono")) ;; nil

引用和事务内存

1(def movie (ref "star wars"))
2movie ;; #object[clojure.lang.Ref 0x3441e2c1 {:status :ready, :val "star wars"}]
3(deref movie) ;; "star wars"
4@movie ;; "star wars"
5
6(alter movie str ": hah") ;; 只能在事务中修改状态
7;; Execution error (IllegalStateException) at user/eval2102 (REPL:1).
8;; No transaction running
9(dosync (alter movie str ": hah")) ;; 通过 dosync 在事务中修改
10;; "star wars: hah"
11@movie ;; "star wars: hah"
12;; Clojure 大部分使用 FP,对于可变的那些使用 STM(软件事务内存)

原子

代理

future

feeling

Lisp 复杂化了,有 Lisp 优点也有 Lisp 缺点

尾递归很难受

并发:事务内存