動態類型語言,少了靜態類型語言必須聲明變量類型的累贅,但也缺失了編譯時類型檢查和編譯時優化的好處。cljs雖然做爲動態類型語言,但其提供Metadata讓咱們在必要的時候可選擇地補充類型提示,以便提升代碼可讀性和供編譯器優化使用。除了上述之外,Metadata還讓咱們在不影響對象本質的前提下,附加額外信息加強元編程能力。html
首先要明確一點的是,Metadata不是任何對象/值都擁有的。只有以下的對象纔可附加Metadata編程
Symbol函數
Var單元測試
Collections(List,Map,Vector,Set)測試
Record優化
Typecode
meta
讀取Metadata 經過meta
咱們能夠獲取對象的Metadata,若沒有則返回nil
。
示例1:獲取Var的Metadatahtm
(def a 1) (meta #'a) ;;=> {:ns cljs.user, :name a, :file "<cljs repl>", :end-column 7, :source "a", :column 1, :line 1, :end-line 1, :arglists (), :doc nil, :test nil}
上述示例1中是(meta #'a)
而不是(meta a)
,前者是獲取Var的Metadata,然後者是獲取值1的Metadata,顯而後者是沒有Metadata的。
示例2:獲取Symbol的Metadata對象
(def a (with-meta 'a {:something "test"})) (meta a) ;;=> {:something "test"}
經過with-meta
咱們能夠獲取附加了metadata的symbol'a
(注意做爲入參的symbol'a
不會受到影響)。blog
with-meta
後期追加Metadata 上面咱們已經看到with-meta
的使用示例了,下面咱們再看看具體的函數簽名吧。
;; Returns an object of the same type and value as obj, with map m as its metadata. (with-meta obj m)
值得注意的是,with-meta
會的返回值纔會附加上metadata,而入參obj不會附加上metadata。所以須要用綁定來保存結果,以便後續使用。
(def a (with-meta obj m))
除了with-meta
後期追加外,不少時候咱們是在定義時就已經能夠明確metadata的了,那麼能夠兩種形式定義metadata。
;; 定義Var的metadata (def ^{:dynamic true, :tag "test"} a 1) ;; 讀取metadata (meta #'a) ;; 定義Map的metadata (def b ^{:something "test"} {:name 1}) ;; 讀取metadata (meta b)
有時咱們只想定義一兩個metadata,完整寫法顯然有些累贅,那麼咱們就能夠採用metadata reader的寫法,小清新一下。
(def ^:dynamic ^"test" a 1) ;;等價於(def ^{:dynamic true, :tag "test"} a 1)
縮寫是有限制,因此只能表達以下metadata
^:foo ;;=> ^{:foo true} ^"foo";;=> ^{:tag "foo"} ^foo ;;=> ^{:tag <value of foo>}
&esmp;至於其它metadata則仍是要使用完整寫法處理。
:dynamic ;; Boolean, 指定Var爲動態綁定 :private ;; Boolean, 指定該Symbol的訪問控制爲私有,默認爲public :doc ;; String, 設置document string :test ;; Function,不帶入參的函數,單元測試函數 :tag ;; Class,指定Symbol所指向的Var的數據類型
另外編譯器會自動附加一下信息到Var上。
:file ;; String :line ;; Int :name ;; Symbol :ns ;; Symbol :macro ;; Boolean,true表示是macro :arglists ;; List<Vector>,每一個Vector表示一個函數簽名
今天就寫到這裏,下次繼續^_^
尊重原創,轉載請註明來自:http://www.cnblogs.com/fsjohn... ^_^肥仔John