Clojure
Lisp on JVM
动态类型
并发:事务内存、代理
前缀表达式
1(mod 5 / 4) ;; 12(+ 1 1 1 1) ;; 43(/ 8 2 2) ;; 24(< 1 2 4) ;; true5(< 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)) ;; 14(last '(1 2 3)) ;; 35(rest '(1 2 3)) ;; (2 3)6(cons :droid '(:r2d2 :c3po)) ;; (:droid :r2d2 :c3po)
向量,与列表不同在于随机访问优化
1(first [:hutt :wookie :ewok]) ;; :hutt2(nth [:hutt :wookie :ewok] 2) ;; :ewok3([:hutt :wookie :ewok] 2) ;; :ewok4(last [:hutt :wookie :ewok]) ;; :ewok5(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) ;; 26(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"34;; doc5(defn do-it6 "do something"7 [what]8 (str "use the " what))910(doc do-it)11;; ([what])12;; do something13;; nil
绑定
1(defn get-age [{age :age}] age)2(get-age person) ;; 1934;; 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 22(map #(count %) ["hgk" "lj"])) ;; 3 234(apply + [1 2 3]) ;; 65(apply max [1 2 3]) ;; 367(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 参数立即执行34(macroexpand '#(count %))5;; (fn* [p1__2085#] (count p1__2085#)) 宏展开,查看定义的宏,前面要加 ' ,注释 ;、引用 '、匿名函数 # 都是宏67(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"56(alter movie str ": hah") ;; 只能在事务中修改状态7;; Execution error (IllegalStateException) at user/eval2102 (REPL:1).8;; No transaction running9(dosync (alter movie str ": hah")) ;; 通过 dosync 在事务中修改10;; "star wars: hah"11@movie ;; "star wars: hah"12;; Clojure 大部分使用 FP,对于可变的那些使用 STM(软件事务内存)
原子
代理
future
feeling
Lisp 复杂化了,有 Lisp 优点也有 Lisp 缺点
尾递归很难受
并发:事务内存