(operator operand1 operand2 ... operandn)
(操作符 参数1 参数2 ....)e.g.(+ 1 2 3)
if一般的结构是:
(if boolean-form
then-form
optional-else-form)
下面是一个例子:
(if (= 2 2)
"OK"
"ERROR")
; => "OK"
注意每一个分支,if只能有一种形式。这是大多数语言不同。例如,在Ruby中,可以这样写:
if true
doer.do_thing(1)
doer.do_thing(2)
else
other_doer.do_thing(1)
other_doer.do_thing(2)
end
为了解决这个明显的限制,我们用do来操作:
do可以让你“wrap up”多种形式。例如REPL:
(if true
(do (println "Success!")
"OK")
(do (println "Failure :(")
"ERROR"))
; => Success!
; => "OK"
在这种情况下,Success!被印在REPL和“OK"返回为整个if表达式的值。
当操作者就像是if和do的一个组合,做,但没有else的形式用when。例如:
(when true
(println "Success!")
"abra cadabra")
; => Success!
; => "abra cadabra"
用when的时候即当某个条件为真时,你想要做多个事情;当条件为假时使用的,不想做任何事情。
3 def
使用def将名字绑定到Clojure中的值:
(def failed-protagonist-names
["Larry Potter"
"Doreen the Explorer"
"The Incredible Bulk"])
在这种情况下,你要绑定的名称 failed-protagonist-names 包含三个字符串的向量。请注意,我使用术语“绑定”,而在其他语言你会说,赋值给一个变量。例如,在Ruby中,你可能会执行多个任务给一个变量,以“build up”它的值:
severity = :mild
error_message = "OH GOD! IT'S A DISASTER! WE'RE "
if severity == :mild
error_message = error_message + "MILDLY INCONVENIENCED!"
else
error_message = error_message + "DOOOOOOOMED!"
end
等效的Clojure是:
(def severity :mild)
(def error-message "OH GOD! IT'S A DISASTER! WE'RE ")
(if (= severity :mild)
(def error-message (str error-message "MILDLY INCONVENIENCED!"))
(def error-message (str error-message "DOOOOOOOMED!")))
然而,这是非常糟糕的Clojure。现在,你应该把def作为它定义的常量。But,you'll learn how to work with this apparent limitation by coding in the functional style later.failed_protagonist_names = [
"Larry Potter",
"Doreen the Explorer",
"The Incredible Bulk"
]
failed_protagonist_names[0] = "Gary Potter"
failed_protagonist_names
# => [
# "Gary Potter",
# "Doreen the Explorer",
# "The Incredible Bulk"
# ]
接下来,是更多关于Clojure的如何实现(nil? 1)
; => false
(nil? nil)
; => true
nil和false用于表示逻辑falsiness,而所有其他值在逻辑上是truth。 =是相等运算符:
(= 1 1)
; => true
(= nil nil)
; => true
(= 1 2)
; => false
93
1.2
1/5
93 integer;1.2 float;1/5 ratio
3.3 string
Clojure中只允许“ ”来界定字符串。比如‘cpp’,就不是一个有效的字符串。Clojure没有字符串插值。它仅允许通过函数级联str:
(def name "Chewbacca")
(str "\"Uggllglglglglglglglll\" - " name)
; => "Uggllglglglglglglglll" - Chewbacca
3.4 Maps
maps在其他语言是类似于dictionaries or hashes。他们一些值联系一些值的一种方式。下面是例子:
;; 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"}}
请注意,maps的值可以是任何类型的。string,number,map,vector,甚至是 function 。 (get {:a 0 :b 1} :b)
; => 1
(get {:a 0 :b {:c "ho hum"}} :b)
; => {:c "ho hum"}
若果key查找不到,get将返回nil,但是你可以给一个默认值
(get {:a 0 :b 1} :c)
; => nil
(get {:a 0 :b 1} :c "UNICORNS")
; => "UNICORNS"
该get-in函数可以让你在嵌套的maps里查找value:
(get-in {:a 0 :b {:c "ho hum"}} [:b :c])
; => "ho hum"
[:b :c]
是一个 vector
另一种方法来查找一个值的映射是将maps看做一个函数,用key作为其参数:
({:name "The Human Coffee Pot"} :name)
; => "The Human Coffee Pot"
3.5 Keywords
一般用做map中的key
:a
:rumplestiltsken
:34
:_?
关键字可以作为函数来查找对应在数据结构中的值。例如:
;; Look up :a in map
(:a {:a 1 :b 2 :c 3})
; => 1
;; This is equivalent to:
(get {:a 1 :b 2 :c 3} :a)
; => 1
;; Provide a default value, just like get:
(:d {:a 1 :b 2 :c 3} "FAERIES")
; => "FAERIES
可以用hash-map来创建一个map
(hash-map :a 1 :b 2)
; => {:a 1 :b 2}
也可以创建sorted maps
3.6 Vectors
Vectors类似于array,都是0-indexed集合
;; 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"}
就像在maps中查找值一样,我们同样使用get函数取值,接下来的章节解释了为什么这样做。
创建vector
(vector "creepy" "full" "moon")
; => ["creepy" "full" "moon"]
添加元素会添加到vector最后
(conj [1 2 3] 4)
; => [1 2 3 4]
3.7 Lists
Lists类似于vectors,他们都是值得线性集合,但是也有一些差别,不能用get检索列表(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
(list 1 2 3 4)
; => (1 2 3 4)
添加元素的话,会添加到list的头部
(conj '(1 2 3) 4)
; => (4 1 2 3)
何时使用list,何时使用vector,建议最好用vector
3.8 Sets
sets是唯一值的集合
;; 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函数创建套现有 vectors 和lists。一个不明显的用途是可以检查一个元素是否在一个集合中存在
(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
可以创建hash sets 和sorted sets
(hash-set 1 1 3 1 2)
; => #{1 2 3}
(sorted-set :b :a :c)
; => #{:a :b :c}
(def failed-movie-titles ["Gone With the Moving Air" "Swellfellas"])
def用名为failed-movie-titles的symbol 连接值[“Gone With the Moving Air”,“Swellfellas”]
Lisp,允许操纵多种symbols作为data,当开始用macros(宏)工作时,我们会看到很多例子。函数可以返回symbols,也可以把它们作为参数:
;; Identity returns its argument (identity 'test) ; => test
failed-protagonist-names
; => ["Larry Potter" "Doreen the Explorer" "The Incredible Bulk"]
(first failed-protagonist-names)
; => "Larry Potter"
引用一个symbol就是告诉Clojure中使用的symbol本身作为一种 data structure,而不是symbol引用的object:
'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-namesYou can also like lists, maps, and vectors. All within the collection will be unevaluated:
您还可以quote collections如lists, maps, and vectors.。symbols时在集合中的所有符号都会被不计算:
'(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