閱讀364 返回首頁    go 阿裏雲 go 技術社區[雲棲]


(cljs/run-at (JSVM. :all) "Metadata就這樣哦")

前言

 動態類型語言,少了靜態類型語言必須聲明變量類型的累贅,但也缺失了編譯時類型檢查和編譯時優化的好處。cljs雖然作為動態類型語言,但其提供Metadata讓我們在必要的時候可選擇地補充類型提示,以便提高代碼可讀性和供編譯器優化使用。除了上述以外,Metadata還讓我們在不影響對象本質的前提下,附加額外信息增強元編程能力。

Metadata附加的目標

 首先要明確一點的是,Metadata不是任何對象/值都擁有的。隻有如下的對象才可附加Metadata
1. Symbol
2. Var
3. Collections(List,Map,Vector,Set)
4. Record
5. Type

meta讀取Metadata

 通過meta我們可以獲取對象的Metadata,若沒有則返回nil
示例1:獲取Var的Metadata

(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不會受到影響)。

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))

定義時附加Metadata

 除了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 Reader

 有時我們隻想定義一兩個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則還是要使用完整寫法處理。

內置的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表示一個函數簽名

總結

 今天就寫到這裏,下次繼續^_^
尊重原創,轉載請注明來自:https://www.cnblogs.com/fsjohnhuang/p/7203927.html ^_^肥仔John

最後更新:2017-10-18 10:33:35

  上一篇:go  Chrome Extension in CLJS —— 搭建開發環境
  下一篇:go  (cljs/run-at (JSVM. :all) "一次說白DataType、Record和Protocol")