咱们知道clojure是Lisp的一种方言,那么这也意味着对这门语言必然植根于“列表解析”。可是在Clojure中,咱们优先使用"序列"来创造列表和管理列表中的元素。 java
以前咱们说过,Lisp系列语言整个都创建在列表之上。咱们使用"list"函数来建立一个列表,但后面你就会发现建立列表的方式不仅一种。若是你不想让你列表中的元素被解释执行,记得引用(quote)一下。 数据结构
=> (list "truck" "car" "bicycle" "plane") ;;建立一个列表 ("truck" "car" "bicycle" "plane") ;;与上面方式等价 => '("truck" "car" "bicycle" "plane") ("truck" "car" "bicycle" "plane") ;;查看列表的类型 =>(class '("truck" "car" "bicycle" "plane")) clojure.lang.PersistentList ;; 给建立的列表绑定一个全局变量 => (def vehicles (list "truck" "car" "bicycle" "plane")) #'user/vehicles ;;查看是不是序列 =>(seq? vehicles) true ;;查看是不是列表 =>(list? vehicles) true ;;查看是不是集合 => (coll? vehicles) true ;;获取第一个元素 =>(first vehicles) "truck" ;;获取第二个元素 =>(second vehicles) "car" ;;获取最后一个元素 =>(last vehicles) "plane" ;;获取除第一个元素之外的剩下列表 =>(rest vehicles) ("car" "bicycle" "plane") ;;获取第n个元素 =>(nth vehicles 0) "truck" =>(nth vehicles 1) "car" ;;添加元素 (这只是返回一个新的列表,vehicles 并不会被改变) => (conj vehicles "motorcycles") ("motorcycles" "truck" "car" "bicycle" "plane")
Cons是lisp语言中另外一个相似列表的一种数据结构。术语”cons“意思就是构造一个对(pair),将这些对连接在一块儿而后造成一个相似列表的数据结构。就像list同样,cons既是一个类型,也是一个函数,咱们可使用cons来建立这种数据结构。 函数
=>(cons "truck" (list "car" "bicycle" "plane")) ("truck" "car" "bicycle" "plane") =>(class (cons "truck" (list "car" "bicycle" "plane"))) clojure.lang.Cons =>(def vehicles (cons "truck" (list "car" "bicycle" "plane"))) #'user/vehicles =>(seq? vehicles) true =>(list? vehicles) false =>(coll? vehicles) true =>(conj vehicles "motorcycle") ("motorcycle" "truck" "car" "bicycle" "plane") =>(class (conj vehicles "motorcycle")) clojure.lang.Cons =>(cons "motorcycle" vehicles) ("motorcycle" "truck" "car" "bicycle" "plane") =>(class (cons vehicles "motorcycle")) clojure.lang.Cons =>(conj "truck" nil) java.lang.ClassCastException: cannot be cast to clojure.lang.IPersistentCollection =>(cons "truck" nil) ("truck") =>(class (cons "truck" nil)) clojure.lang.PersistentList
注意最后一个例子,是否是看起来很奇怪?当咱们使用cons将一个元素附加到一个列表或者另外一个cons结构上时,返回的仍然是一个cons类型结构。可是当咱们将一个item附加nil上时,返回的倒是list类型。这一点尤为注意。 性能
向量是除了list和cons以外的另外一个很受欢迎的数据结构,由于它有时用起来有一些独特的优点。举个例子,由于向量使用方括号来表示,因此至少从视觉上来讲会让它从大量的圆括号中脱颖而出,提供了更好的可读性。另外使用向量一般能提供比列表更好的性能优点。 spa
=>(vector "truck" "car" "bicycle" "plane") ["truck" "car" "bicycle" "plane"]
;;一种简便的建立向量方式,这个不须要“引用”了哦 =>["truck" "car" "bicycle" "plane"] ["truck" "car" "bicycle" "plane"] =>(class ["truck" "car" "bicycle" "plane"]) clojure.lang.PersistentVector =>(def vehicles ["truck" "car" "bicycle" "plane"]) #'user/vehicles =>(seq? vehicles) false =>(list? vehicles) false =>(vector? vehicles) true =>(coll? vehicles) true注意:虽然大多数函数对待向量和列表都会产生相同的结果,但有时候这种假设每每会引入一些问题。看下面例子,注意两者之间的区别:
=> (conj ["a" "b"] "c") ["a" "b" "c"] => (conj '("a" "b") "c") ("c" "a" "b")