抽象
在了解sequence
之前,我们可以先了解下abstraction
,abstraction
的概念在很多语言里面都有,譬如Go
,interface
就是abstraction
:
type IA interface {
DoFunc()
}
type A struct {}
func (a *A) DoFunc() {
}
在上面这个例子中,struct A
实现了DoFunc
函数,我们就可以认为,A
实现了IA
。
Sequence Abstraction
Clojure
也提供了abstraction
的概念,这里我们主要来了解下sequence abstraction
。
在Clojur
e里面,如果这些core
sequence
function
first
,rest
和cons
能够用于某个data structure
,我们就可以认为这个data structure
实现了sequence abstraction
,就能被相关的sequence function
进行操作,譬如map
,reduce
等。
First
first
返回collection
里面的第一个元素,譬如:
user=> (first [1 2 3])
1
user=> (first '(1 2 3))
1
user=> (first #{1 2 3})
1
user=> (first {:a 1 :b 2})
[:a 1]
Rest
rest
返回collection
里面,第一个元素后面的sequence
,譬如:
user=> (rest [1 2 3])
(2 3)
user=> (rest [1])
()
user=> (rest '(1 2 3))
(2 3)
user=> (rest #{1 2 3})
(3 2)
user=> (rest {:a 1 :b 2})
([:b 2])
Cons
Cons
则是将一个元素添加到collection
的开头,譬如:
user=> (cons 1 [1 2 3])
(1 1 2 3)
user=> (cons 1 '(1 2 3))
(1 1 2 3)
user=> (cons 1 #{1 2 3})
(1 1 3 2)
user=> (cons 1 {:a 1 :b 2})
(1 [:a 1] [:b 2])
user=> (cons {:c 3} {:a 1 :b 2})
({:c 3} [:a 1] [:b 2])
从上面的例子可以看出,Clojure
自身的vector
,list
等都实现了sequence abstraction
,所以他们也能够被一些sequence function
调用:
user=> (defn say [name] (str "hello " name))
#'user/say
user=> (map say [1 2])
("hello 1" "hello 2")
user=> (map say '(1 2))
("hello 1" "hello 2")
user=> (map say #{1 2})
("hello 1" "hello 2")
user=> (map say {:a 1 :b 2})
("hello [:a 1]" "hello [:b 2]")
user=> (map #(say (second %)) {:a 1 :b 2})
("hello 1" "hello 2")
Collection Abstraction
跟sequence abstraction
类似,Clojure
里面的core data structure
,譬如vector
,list
等,都实现了collection abstraction
。
Collection abstraction
通常是用于处理整个data structure
的,譬如:
user=> (count [1 2 3])
3
user=> (empty? [])
true
user=> (every? #(< % 3) [1 2 3])
false
user=> (every? #(< % 4) [1 2 3])
true
into
一个重要的collection function
就是into
,sequence function
通常会返回一个seq
,而into
会将返回的seq
转换成原始的data structure
,譬如:
user=> (into [] [1 2 3])
[1 2 3]
user=> (into [] (map inc [1 2 3]))
[2 3 4]