幾分鐘內(nèi)學(xué)習(xí) Clojure

幾分鐘內(nèi)學(xué)習(xí) Clojure - 技術(shù)翻譯 - 開源中國(guó)社區(qū)
https://www.oschina.net/translate/learn-clojure-in-minutes

此處獲取源碼: test.clj
Clojure是JVM上的一個(gè)LISP語(yǔ)言變種。它比Common Lisp更強(qiáng)調(diào)純函數(shù)式編程,但提供了一些STM工具以處理它所引入的狀態(tài)問題。
這個(gè)組合使并行處理更加簡(jiǎn)單,并且通常是自動(dòng)的。
(你需要Clojure 1.2或以上版本。)

; 分號(hào)作為注釋的開始

; Clojure 用一種把元素用括號(hào)括起來的像列表一樣的方式來書寫,元素之間用空格隔開

; 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ì)象類型來表示 布爾值、字符串和數(shù)字

; 使用 class函數(shù)來檢測(cè)它們.

(class 1) ; 整形字面值默認(rèn)是java中的Long類型

(class 1.); 浮點(diǎn)字面值對(duì)應(yīng)著java中的Double類型

(class
""
); 字符串總是用雙引號(hào)括起來,并且對(duì)應(yīng)著java中的Sring類型

(class
false
) ;布爾值對(duì)應(yīng)著java中的Boolean類型

(class nil); null值被稱為 nil(英語(yǔ)含義:無、零點(diǎn))

; 如果你想創(chuàng)建一列數(shù)據(jù)字面值, 使用一個(gè)單引號(hào) ' 來防表達(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))起來

;這樣就能防止解釋器把它當(dāng)做一個(gè)函數(shù)來解析

;另外,(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

; 序列是列表一種邏輯上的接口,可以懶加載.

;
"懶"
意味著可以定義無窮序列,就像下面一樣:

(range 4) ; => (0 1 2 3)

(range) ; => (0 1 2 3 4 ...) (一個(gè)無窮序列)

(take 4 (range)) ; (0 1 2 3)

; 使用cons 來追加一個(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來連接列表和向量

(concat [1 2] '(3 4)) ; => (1 2 3 4)

; 使用filter, map 來進(jìn)行列表計(jì)算

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

(filter even? [1 2 3]) ; => (2)

; 使用reduce 來進(jìn)行化繁為簡(jiǎn) (map
/reduce
思想就來自于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來創(chuàng)建一個(gè)函數(shù)。所有的函數(shù)都有返回值,就是它的最后一個(gè)表達(dá)式

(fn []
"Hello World"
) ; => fn

; (你需要額外的括號(hào)去調(diào)用它)

((fn []
"Hello World"
)) ; =>
"Hello World"

;你可以使用def來創(chuàng)建變量

(def x 1)

x ; => 1

; 將函數(shù)賦值給一個(gè)變量

(def hello-world (fn []
"Hello World"
))

(hello-world) ; =>
"Hello World"

; 你可以使用defn來簡(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} (不保證順序)

; 順便說一下, 逗號(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ù)來調(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 來刪除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來添加新值

(conj

{1 2 3} 4) ; => #{1 2 3 4}

; 使用disj刪除原有值

(disj

{1 2 3} 1) ; => #{2 3}

; 直接將
set
當(dāng)做函數(shù)來測(cè)試是否包含某個(gè)值(NB)

(

{1 2 3} 1) ; => 1 (有就返回原有的值)

(

{1 2 3} 4) ; => nil (沒有就返回nil)

; clojure.sets 命名空間包含更多的函數(shù)

; 一些有用的形式

;;;;;;;;;;;;;;;;;

; clojure中的邏輯結(jié)構(gòu)都是宏, 看起來也沒什么不同

(
if
false
"a"
"b"
) ; =>
"b"

(
if
false
"a"
) ; => nil

; 使用
let
來創(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”來獲得一個(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來導(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))起來了.

(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è)”."用來創(chuàng)建一個(gè)對(duì)象

(Date.) ; <a
date
object>

; 使用. 來調(diào)用方法. 或者使用“.方法名"簡(jiǎn)寫的方式

(. (Date.) getTime) ; <a timestamp>

(.getTime (Date.)) ; 和上面一樣哦

; 使用/ 來調(diào)用靜態(tài)方法

(System
/currentTimeMillis
) ; <a timestamp> (system is always present)

; 使用 doto 來處理可變的類<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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評(píng)論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,238評(píng)論 3 428
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,823評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,339評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,713評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評(píng)論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,893評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,448評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,201評(píng)論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,397評(píng)論 1 372
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,631評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評(píng)論 1 293
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,128評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,347評(píng)論 2 377

推薦閱讀更多精彩內(nèi)容