生活随笔
收集整理的這篇文章主要介紹了
几分钟内学习 Clojure
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
| Clojure是JVM上的一個(gè)LISP語(yǔ)言變種。它比Common Lisp更強(qiáng)調(diào)純函數(shù)式編程,但提供了一些STM工具以處理它所引入的狀態(tài)問題。 這個(gè)組合使并行處理更加簡(jiǎn)單,并且通常是自動(dòng)的。 (你需要Clojure 1.2或以上版本。) | Sweelia 翻譯于 2年前 1人頂 頂?翻譯的不錯(cuò)哦! |
? | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | ; 分號(hào)作為注釋的開始 ; Clojure 用一種把元素用括號(hào)括起來(lái)的像列表一樣的方式來(lái)書寫,元素之間用空格隔開 ; clojure 解釋器會(huì)把第一個(gè)元素當(dāng)做是函數(shù)或者宏調(diào)用,其他的都作為參數(shù) ; 下面這個(gè)函數(shù)用于設(shè)置當(dāng)前的命名空間 (ns?test) ; 更多基本的例子: ; str 函數(shù)會(huì)用它所有的參數(shù)創(chuàng)造一個(gè)字符串 (str?"Hello" " " "World") ; =>?"Hello World" ; 數(shù)學(xué)運(yùn)算很直觀,不過是前綴表達(dá)式 (+ 1 1) ; => 2 (- 2 1) ; => 1 (* 1 2) ; => 2 (/ 2 1) ; => 2 ;? 相等比較使用 “=”符號(hào) (= 1 1) ; =>?true (= 2 1) ; =>?false ; 你也不必?fù)?dān)心邏輯運(yùn)算 (not?true) ; =>?false ; 嵌套方式正如你預(yù)料的那樣 (+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2 ; 類型系統(tǒng) ;;;;;;;;;;;;; ; Clojure 使用java對(duì)象類型來(lái)表示 布爾值、字符串和數(shù)字 ; 使用 `class`函數(shù)來(lái)檢測(cè)它們. (class 1) ; 整形字面值默認(rèn)是java中的Long類型 (class 1.); 浮點(diǎn)字面值對(duì)應(yīng)著java中的Double類型 (class?""); 字符串總是用雙引號(hào)括起來(lái),并且對(duì)應(yīng)著java中的Sring類型 (class?false) ;布爾值對(duì)應(yīng)著java中的Boolean類型 (class nil); null值被稱為 nil(英語(yǔ)含義:無(wú)、零點(diǎn)) ; 如果你想創(chuàng)建一列數(shù)據(jù)字面值, 使用一個(gè)單引號(hào) ' 來(lái)防表達(dá)式被解析執(zhí)行 '(+ 1 2) ; => (+ 1 2) ;這里沒有返回3 ; (上面表達(dá)式和(quote (+ 1 2)) 等價(jià),不過更簡(jiǎn)潔 ; 你可以運(yùn)算一個(gè)引用列表 (eval '(+ 1 2)) ; => 3 ; 集合和序列 ;;;;;;;;;;;;;;;;;;; ; 向量和列表也是java類哦!! (class [1 2 3]); => clojure.lang.PersistentVector (class '(1 2 3)); => clojure.lang.PersistentList ;書寫一個(gè)列表形如(1 2 3)一樣簡(jiǎn)單, 但是我們不得不把它“引”(前面加個(gè)單引號(hào))起來(lái) ;這樣就能防止解釋器把它當(dāng)做一個(gè)函數(shù)來(lái)解析 ;另外,(list 1 2 3) 和 '(1 2 3) 等價(jià) ;列表和向量都是集合: (coll? '(1 2 3)) ; =>?true (coll? [1 2 3]) ; =>?true ; 只有列表是序列.(序列是有順序的) (seq? '(1 2 3)) ; =>?true (seq? [1 2 3]) ; =>?false ; 序列是列表一種邏輯上的接口,可以懶加載. ;?"懶" 意味著可以定義無(wú)窮序列,就像下面一樣: (range 4) ; => (0 1 2 3) (range) ; => (0 1 2 3 4 ...) (一個(gè)無(wú)窮序列) (take 4 (range)) ;? (0 1 2 3) ; 使用cons 來(lái)追加一個(gè)元素到列表或者向量的頭部 (cons 4 [1 2 3]) ; => (4 1 2 3) (cons 4 '(1 2 3)) ; => (4 1 2 3) ; 使用conj追加一個(gè)元素到列表的頭部,或者向量的尾部, (conj [1 2 3] 4) ; => [1 2 3 4] (conj '(1 2 3) 4) ; => (4 1 2 3) ; 使用concat來(lái)連接列表和向量 (concat [1 2] '(3 4)) ; => (1 2 3 4) ; 使用filter, map 來(lái)進(jìn)行列表計(jì)算 (map inc [1 2 3]) ; => (2 3 4) (filter even? [1 2 3]) ; => (2) ; 使用reduce 來(lái)進(jìn)行化繁為簡(jiǎn)? (map/reduce 思想就來(lái)自于lisp) (reduce + [1 2 3 4]) ; = (+ (+ (+ 1 2) 3) 4) ; => 10 ; Reduce 可以使用一個(gè)初始值 (reduce conj [] '(3 2 1)) ; = (conj (conj (conj [] 3) 2) 1) ; => [3 2 1] ; 函數(shù) ;;;;;;;;;;;;;;;;;;;;; ; 使用fn來(lái)創(chuàng)建一個(gè)函數(shù)。所有的函數(shù)都有返回值,就是它的最后一個(gè)表達(dá)式 (fn []?"Hello World") ; => fn ; (你需要額外的括號(hào)去調(diào)用它) ((fn []?"Hello World")) ; =>?"Hello World" ;你可以使用def來(lái)創(chuàng)建變量 (def x 1) x ; => 1 ; 將函數(shù)賦值給一個(gè)變量 (def hello-world (fn []?"Hello World")) (hello-world) ; =>?"Hello World" ; 你可以使用defn來(lái)簡(jiǎn)化定義過程 (defn hello-world []?"Hello World") ;[] 是函數(shù)的參數(shù)列表 (defn hello [name] ??(str?"Hello " name)) (hello?"Steve") ; =>?"Hello Steve" ; 你也可以使用下面這種簡(jiǎn)寫方式 (def hello2?#(str "Hello " %1)) (hello2?"Fanny") ; =>?"Hello Fanny" ; 你可以創(chuàng)建擁有可變參數(shù)的函數(shù) (defn hello3 ??([]?"Hello World") ??([name] (str?"Hello " name))) (hello3?"Jake") ; =>?"Hello Jake" (hello3) ; =>?"Hello World" ; 函數(shù)允許將參數(shù)打包成列表 (有點(diǎn)類似python中的*) (defn count-args [& args] ??(str?"You passed " (count args)?" args: " args)) (count-args 1 2 3) ; =>?"You passed 3 args: (1 2 3)" ; 你可以將普通參數(shù)和列表參數(shù)混合使用 (defn hello-count [name & args] ??(str?"Hello " name?", you passed " (count args)?" extra args")) (hello-count?"Finn" 1 2 3) ; =>?"Hello Finn, you passed 3 extra args" ; 哈希表 ;;;;;;;;;; (class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap ; 關(guān)鍵字類似字符串,但是做了一些性能上的優(yōu)化 (class :a) ; => clojure.lang.Keyword ; Maps 的鍵可以是任意類型,但是通常推薦使用keywords (def stringmap (hash-map?"a" 1,?"b" 2,?"c" 3)) stringmap? ; => {"a" 1,?"b" 2,?"c" 3} (def keymap (hash-map :a 1 :b 2 :c 3)) keymap ; => {:a 1, :c 3, :b 2} (不保證順序) ; 順便說(shuō)一下, 逗號(hào)只是為了看著更清晰,其他都和空格一樣,什么都不做. ; 從一個(gè)map中檢索一個(gè)值,可以直接把這個(gè)map當(dāng)做函數(shù)調(diào)用(這個(gè)NB) (stringmap?"a") ; => 1 (keymap :a) ; => 1 ; 關(guān)鍵字也可以當(dāng)做函數(shù)來(lái)調(diào)用,從一個(gè)map中檢索值(這個(gè)更NB) (:b keymap) ; => 2 ; stings 可沒有這個(gè)功能,所以下面會(huì)拋出異常。(這也是為什么推薦使用keywords) ;("a" stringmap) ; => Exception: java.lang.String cannot be cast to clojure.lang.IFn ; 檢索一個(gè)不存在的值會(huì)返回nil (stringmap?"d") ; => nil ; 使用assoc 向一個(gè)map中添加新的鍵值對(duì)。 (assoc keymap :d 4) ; => {:a 1, :b 2, :c 3, :d 4} ; 請(qǐng)記住, clojure 類型是不可變的! keymap ; => {:a 1, :b 2, :c 3} ; 使用dissoc 來(lái)刪除key(可以刪除多個(gè)) (dissoc keymap :a :b) ; => {:c 3} ; 集合 ;;;;;; (class?#{1 2 3}) ; => clojure.lang.PersistentHashSet (set [1 2 3 1 2 3 3 2 1 3 2 1]) ; =>?#{1 2 3} ; 使用con來(lái)添加新值 (conj?#{1 2 3} 4) ; => #{1 2 3 4} ; 使用disj刪除原有值 (disj?#{1 2 3} 1) ; => #{2 3} ; 直接將set當(dāng)做函數(shù)來(lái)測(cè)試是否包含某個(gè)值(NB) (#{1 2 3} 1) ; => 1? (有就返回原有的值) (#{1 2 3} 4) ; => nil (沒有就返回nil) ; clojure.sets 命名空間包含更多的函數(shù) ; 一些有用的形式 ;;;;;;;;;;;;;;;;; ; clojure中的邏輯結(jié)構(gòu)都是宏, 看起來(lái)也沒什么不同 (if false "a" "b") ; =>?"b" (if false "a") ; => nil ; 使用let 來(lái)創(chuàng)建臨時(shí)綁定 (let [a 1 b 2] ??(> a b)) ; =>?false ; 執(zhí)行多條語(yǔ)句,返回最后一條語(yǔ)句 (do ??(print?"Hello") ??"World") ; =>?"World" (prints?"Hello") ; 所有的函數(shù)都包含一個(gè)隱式的do (defn print-and-say-hello [name] ??(print?"Saying hello to " name) ??(str?"Hello " name)) (print-and-say-hello?"Jeff") ;=>?"Hello Jeff" (prints?"Saying hello to Jeff") ;?let綁定也是哦 (let [name?"Urkel"] ??(print?"Saying hello to " name) ??(str?"Hello " name)) ; =>?"Hello Urkel" (prints?"Saying hello to Urkel") ; 模塊 ;;;;;;;;;;;;;;; ; 使用“use”來(lái)獲得一個(gè)模塊中所有的函數(shù) (use 'clojure.set) ; 現(xiàn)在我們可以使用集合操作 (intersection?#{1 2 3} #{2 3 4}) ; => #{2 3}? 求交集 (difference?#{1 2 3} #{2 3 4}) ; => #{1}?? 求差集 ; 你可以只導(dǎo)入一個(gè)函數(shù)子集(例如下面只包含交集函數(shù)) (use '[clojure.set :only [intersection]]) ; 使用reqire來(lái)導(dǎo)入一個(gè)模塊 (require 'clojure.string) ; 使用/從一個(gè)模塊中調(diào)用函數(shù) (clojure.string/blank??"") ; =>?true ; 你可以在導(dǎo)入模塊的時(shí)候自定義名稱 (require '[clojure.string :as str])? (str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst." ; (#"" denotes a regular expression literal) ; 你可以使用":require" 從一個(gè)命名空間中引入模塊(use也可以,但是別這么做) ; 如果你使用:require的話,就沒必要把模塊“引”(前面加個(gè)單引號(hào))起來(lái)了. (ns?test ??(:require ????[clojure.string :as str] ????[clojure.set :as?set])) ; Java ;;;;;;;;;;;;;;;;; ; java 擁有一個(gè)龐大的各種用途的標(biāo)準(zhǔn)庫(kù),你一定迫不及待想學(xué)習(xí)如何在clojure中使用這些庫(kù) ; 使用import類引入java模塊(這個(gè)還好沒變化) (import java.util.Date) ; 你也可以從一個(gè)命名空間中引入 (ns?test ??(:import java.util.Date ???????????java.util.Calendar)) ; 類名字后加個(gè)”."用來(lái)創(chuàng)建一個(gè)對(duì)象 (Date.) ; <a?date object> ; 使用. 來(lái)調(diào)用方法. 或者使用“.方法名"簡(jiǎn)寫的方式 (. (Date.) getTime) ; <a timestamp> (.getTime (Date.)) ; 和上面一樣哦 ; 使用/ 來(lái)調(diào)用靜態(tài)方法 (System/currentTimeMillis) ; <a timestamp> (system is always present) ; 使用 doto 來(lái)處理可變的類<span style="font-family:宋體;">,所有的函數(shù)始終用最初的那個(gè)對(duì)象值,最后還是返回最初的那個(gè)對(duì)象</span> ?(import java.util.Calendar) (doto (Calendar/getInstance) ??(.set 2000 1 1 0 0 0) ??.getTime) ; => A Date.?set to 2000-01-01 00:00:00 | |
總結(jié)
以上是生活随笔為你收集整理的几分钟内学习 Clojure的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。