语法
形式/Forms
- 数据:nubmbers,strings,maps,vectors
- 操作
数据:
1
“a string”
[“a” “vector” “of” “strings”]
操作:由( )规范
(operator operand1 operand2 … operandn)
例子:
(+ 1 2 3)
; => 6
(str “It was the panda ” “in the library ” “with a dust buster”)
; => “It was the panda in the library with a dust buster”
控制(control flow)
if
格式:
(if boolean-form
then-form
optional-else-form)
例子:
(if true
“abra cadabra”
“hocus pocus”)
; => “abra cadabra”
一个分支只能有一个表达式(form/expression)
如果要写多个form,则需要do
do
示例:
(if true
(do (println “Success!”)
“abra cadabra”)
(do (println “Failure :(“)
“hocus pocus”))
; => Success!
; => “abra cadabra”
when
是if和do的组合,但没有else
(when true
(println “Success!”)
“abra cadabra”)
; => Success!
; => “abra cadabra”
定义变量(def)
(def failed-protagonist-names
[“Larry Potter”
“Doreen the Explorer”
“The Incredible Bulk”])
数据结构
nil, true, false, Truthiness, Equality
nil : 相当于null,也代表false,除了nil和false之外,其他值都当做true
(nil? 1)
; => false
(nil? nil)
; => true
(= 1 1)
; => true
(= nil nil)
; => true
(= 1 2)
; => false
numbers
string
只能用双引号表示,连接只能用str函数
(def name “Chewbacca”)
(str “\”Uggllglglglglglglglll\” - ” name)
; => “Uggllglglglglglglglll” - Chewbacca
map
创建
;; An empty map
{};; “:a”, “:b”, “:c” are keywords and we’ll cover them in the next section
{:a 1
:b “boring example”
:c []};; Associate “string-key” with the “plus” function
{“string-key” +};; Maps can be nested
{:name {:first “John” :middle “Jacob” :last “Jingleheimerschmidt”}}
用函数创建
(hash-map :a 1 :b 2)
; => {:a 1 :b 2}
读取key
(get {:a 0 :b 1} :b)
; => 1
(get {:a 0 :b {:c “ho hum”}} :b)
; => {:c “ho hum”}(get {:a 0 :b 1} :c)
; => nil
; 指定默认为空的返回值
(get {:a 0 :b 1} :c “UNICORNS”)
; => “UNICORNS”
get-in读取内嵌map
(get-in {:a 0 :b {:c “ho hum”}} [:b :c])
; => “ho hum
vector
;; Here’s a vector literal
[3 2 1]
;; Here we’re returning an element of a vector
(get [3 2 1] 0)
; => 3
;; Another example of getting by index. Notice as well that vector
;; elements can be of any type and you can mix types.
(get [“a” {:name “Pugsley Winterbottom”} “c”] 1)
; => {:name “Pugsley Winterbottom”}
用函数创建:
(vector “creepy” “full” “moon”)
; => [“creepy” “full” “moon”]
添加:
(conj [1 2 3] 4)
; => [1 2 3 4]
list
;; Here’s a list - note the preceding single quote
‘(1 2 3 4)
; => (1 2 3 4)
;; Notice that the REPL prints the list without a quote. This is OK,
;; and it’ll be explained later.
;; Doesn’t work for lists
(get ‘(100 200 300 400) 0)
;; This works but has different performance characteristics which we
;; don’t care about right now.
(nth ‘(100 200 300 400) 3)
; => 400
创建:
(list 1 2 3 4)
; => (1 2 3 4)
添加:
(conj ‘(1 2 3) 4)
; => (4 1 2 3)
set
;; Literal notation
#{“hannah montanna” “miley cyrus” 20 45}
;; If you try to add :b to a set which already contains :b,
;; the set still only has one :b
(conj #{:a :b} :b)
; => #{:a :b}
;; You can check whether a value exists in a set
(get #{:a :b} :a)
; => :a
(:a #{:a :b})
; => :a
(get #{:a :b} “hannah montanna”)
; => nil
用函数创建:
(set [3 3 3 4 4])
; => #{3 4}
;; 3 exists in vector
(get (set [3 3 3 4 4]) 3)
; => 3
;; but 5 doesn’t
(get (set [3 3 3 4 4]) 5)
; => nil
sorted-set
(sorted-set :b :a :c)
; => #{:a :b :c}
Symbols and Naming
Symbol :可以理解为形参
(def failed-movie-titles [“Gone With the Moving Air” “Swellfellas”])
quoting
引用,即symbol本身,而不是symbol代表的value
‘failed-protagonist-names
; => failed-protagonist-names
;; 获取变量值
(eval ‘failed-protagonist-names)
; => [“Larry Potter” “Doreen the Explorer” “The Incredible Bulk”]
(first ‘failed-protagonist-names)
; => Throws exception!
(first [‘failed-protagonist-names ‘failed-antagonist-names])
; => failed-protagonist-names
‘(failed-protagonist-names 0 1)
; => (failed-protagonist-names 0 1)
(first ‘(failed-protagonist-names 0 1))
; => failed-protagonist-names
(second ‘(failed-protagonist-names 0 1))
; => 0
Simplicity
Clojure 设计哲学:
It is better to have 100 functions operate on one data structure
than 10 functions on 10 data structures.
– Alan Perlis
故clojure没有类的概念,通常使用built-in数据结构
Functions
定义函数表达式:返回的也是函数
;; Return value of “or” is first truthy value, and + is truthy,or是函数,参数是 +,-,因为除了nil和false是false以外,任何其他值都为true,故返回了+,而+ 也代表了函数,故这个一个函数表达式,返回了一个代表+ 运算的函数
(or + -)
;;所以如下代表了求和操作
((or + -) 1 2 3)
; => 6
;;相同的,可以通过and来实现相同的功能
;; Return value of “and” is first falsey value or last truthy value.
;; + is the last truthy value
((and (= 1 1) +) 1 2 3)
;; 通过first实现相同的功能
;; Return value of “first” is the first element in a sequence
((first [+ 0]) 1 2 3)
map 函数,将 任意函数,应用于集合上
;; The “inc” function increments a number by 1
(inc 1.1)
; => 2.1
;; 注意返回的不是vector
(map inc [0 1 2 3])
; => (1 2 3 4)
定义函数 (defn)
(defn too-enthusiastic
“(docstring) Return a cheer that might be a bit too enthusiastic”
[name]
(str “OH. MY. GOD! ” name ” YOU ARE MOST DEFINITELY LIKE THE BEST ”
“MAN SLASH WOMAN EVER I LOVE YOU AND WE SHOULD RUN AWAY TO SOMEWHERE”))(too-enthusiastic “Zelda”)
; => “OH. MY. GOD! Zelda YOU ARE MOST DEFINITELY LIKE THE BEST MAN
函数重载
(defn multi-arity
;; 3-arity arguments and body
([first-arg second-arg third-arg]
(do-things first-arg second-arg third-arg))
;; 2-arity arguments and body
([first-arg second-arg]
(do-things first-arg second-arg))
;; 1-arity arguments and body
([first-arg]
(do-things first-arg)))
传入可变参数
(defn codger-communication
[whippersnapper]
(str “Get off my lawn, ” whippersnapper “!!!”))(defn codger
[& whippersnappers] ;; the ampersand indicates the “rest-param”
(map codger-communication whippersnappers))(codger “Billy” “Anne-Marie” “The Incredible Bulk”)
; =>
; (“Get off my lawn, Billy!!!”
; “Get off my lawn, Anne-Marie!!!”
; “Get off my lawn, The Incredible Bulk!!!”)
Destructuring
;; Return the first element of a collection
(defn my-first
[[first-thing]] ; Notice that first-thing is within a vector
first-thing)(my-first [“oven” “bike” “waraxe”])
; => “oven”
等价于:
(defn my-other-first
[collection]
(first collection))
(my-other-first [“nickel” “hair”])
; => “nickel”
传入map,:lat, :lng作为key,lat,lng为name
(defn announce-treasure-location
[{lat :lat lng :lng}]
(println (str “Treasure lat: ” lat))
(println (str “Treasure lng: ” lng)))
(announce-treasure-location {:lat 28.22 :lng 81.33})
; =>
; Treasure lat: 28.22
; Treasure lng: 81.33
等价于:
;; Works the same as above.
(defn announce-treasure-location
[{:keys [lat lng]}]
(println (str “Treasure lat: ” lat))
(println (str “Treasure lng: ” lng)))
获取map本身,通过as
;; Works the same as above.
(defn receive-treasure-location
[{:keys [lat lng] :as treasure-location}]
(println (str “Treasure lat: ” lat))
(println (str “Treasure lng: ” lng));; One would assume that this would put in new coordinates for your ship
(steer-ship! treasure-location))
函数体(function body)
返回最后一行
(defn illustrative-function
[]
(+ 1 304)
30
“joe”)
(illustrative-function)
; => “joe”
匿名函数
;; 用fn创建
;;This looks a lot like defn, doesn’t it?
(fn [param-list]
function body);; Example
(map (fn [name] (str “Hi, ” name))
[“Darth Vader” “Mr. Magoo”])
; => (“Hi, Darth Vader” “Hi, Mr. Magoo”);; Another example
((fn [x] (* x 3)) 8)
; => 24
;; 为匿名函数取名
(def my-special-multiplier (fn [x] (* x 3)))
(my-special-multiplier 12)
; => 36
# 方式,更紧凑的实现方式
;; Whoa this looks weird.
#(* % 3)
;; Apply this weird looking thing
(#(* % 3) 8)
; => 24
;; Another example
(map #(str “Hi, ” %)
[“Darth Vader” “Mr. Magoo”])
; => (“Hi, Darth Vader” “Hi, Mr. Magoo”)