今天是深夜模式,走凌晨發文路線~
在Clojure裡Map類似Python的Disctionary, Ruby的Hash和Javascript的Object。
Javascript | Clojurescript |
---|---|
Object {a: 1, b: 2} | Map {:a 1, :b 2} |
JS Console:
Clojure的Map:
你會問,那前面有冒號:
的是什麼呢?那叫做Keyword
tutorial.core=> {}
{}
tutorial.core=> {:a 1, :b 2 }
{:a 1, :b 2}
昨天的鐵人賽文章有講到用來取Vector的值可以用get
(get ["the Philosopher's Stone" "the Chamber of Secrets" "the Prisoner of Azkaban"] 2)
"the Prisoner of Azkaban"
取Map得值,要用的是keyword
(get {:c {:a 1, :b 2}} :c)
=>{:a 1, :b 2}
但如果我們視{}
Map為一個function的話,get也可以省略
({:c {:a 1, :b 2}} :c)
=> {:a 1, :b 2}
map也可以設為巢狀 nested map
{:c {:a 1, :b 2}}
nested map取值使用的是 get-in,
第一個參數是nested map,後面第二個參數是的要取的那個value的nested keyword[]
,有一個以上,用vector裝起來
(get-in {:c {:a 1, :b 2}} [:c :a])
=> 1
(get-in {:c {:a 1, :b 2}} [:c :b])
=> 2
舉個context比較有意涵的例子,
假設 error-msg
設定為一個nested-map
;; 表單裡,家用電話error-msg必須是nil(就是必填的意思啦)
(is (= nil (get-in error-msg [:home :phone-no])))
;; 表單裡,手機號碼的國碼error-msg必須是nil(就是必填的意思啦)
(is (= nil (get-in error-msg [:mobile :country-code])))
跟一般map取值不同,
nested map取值,get-in就不能省略不寫了唷~
我們可以使用第二篇文章學過的defn
以及keyword
api來定義一個可以建立map
的function:
(defn creating-map
[key value]
{(keyword key) value})
tutorial.core=> (creating-map "Taiwan" "Taipei")
{:Taiwan "Taipei"}
然後用def
放進變數
tutorial.core=> (def capital (creating-map "Taiwan" "Taipei"))
#'tutorial.core/capital
tutorial.core=> capital
{:Taiwan "Taipei"}
最後來個keywords小提醒~
如果是指定某個namespaced的keywords,需要使用雙冒號 ::
;; 定義新的變數example,用來存放 namespaced的keywords
tutorial.core=> (def example ::ns-example)
#'tutorial.core/example
;; 換成新的namespaced keyword
tutorial.core=> (ns ns-example)
nil
;; namespace已改為ns-example
ns-example=>
;; :tutorial.core/ns-example 這個keyword就是定義好的example變數
ns-example=> (= tutorial.core/example :tutorial.core/ns-example)
true
為了不要離正題Collection
太遠,有機會的話之後會再深入聊一下namespace。
明天請繼續收看collection的第四集:Sets!