schema是描寫敘述數據形式的一種clojure數據結構,可用於文件、校驗函數和數據。html
如下舉個樣例讓你們對schema有個總體認識.java
例:git
(ns schema-examplesgithub
(:require [schema.core :as s]))數組
(def s-type s/Str)數據結構
(s/validate s-type "123") ;; Success!函數
(s/validate s-type 123) ;; Exception -- Value does not match schema:...工具
(1)project.clj的:dependencies中加入「[prismatic/schema "0.3.1"]」包。ui
(2)在命名空間的:require中增長「[schema.core :as s]」。spa
(1)支持java所定義的所有數據類型(包含基本數據類型和複雜數結構),schema封裝了好多Java的數據類型,如Int Str等。
[詳見](http://prismatic.github.io/schema/schema.core.html)
例:(def data long)
(def map-shape java.util.Map)
(2)支持schema.core定義的數據類型
例:(def s-data s/Int)
(def s-str s/Str)
(def s-keyword s/Keyword)
(3)支持本身定義數據類型
例:
(def Data
{:a {:b s/Str
:c s/Int}
:d [{:e s/Keyword
:f [s/Num]}]})
(4)可以利用schema提供的工具函數來定義類型
例:
定義一個數據必須是奇數且爲長整形的:
(def OddLong (s/both long (s/pred odd? 'odd?
)))
(都不用你再寫一個檢查函數了,很是方便啊。有木有!!)
(5)對於Map的schema。在定義的時候還可以設定可選項
如:
(def FancyMap
{(s/optional-key :foo) s/Keyword
s/Str s/Str})
(s/validate FancyMap {"a" "b"})
(s/validate FancyMap {:foo :f "c" "d" "e" "f"})
注意:key 和 value應該是成對出現或消失的。
(s/validate FancyMap {:foo "c" "d" "e" "f"}) ;; Exception -- Value does not match schema:...
(6)你可以用s/validate函數來檢測你定義的數據是否知足你定義的類型。
還可以用s/explain函數來檢查某個類型的定義。
如:
(s/validate FancyMap {"a" "b"})
(s/explain FancyMap)
可以用schema.core中的def來定義一個變量, 如:
(s/def foo :- long 2)
要求用於變量初始化的值必須知足定義的schema.
schema.core中封裝了好多函數, 咱們可以利用s/defn或s/fn來定義咱們的函數,和用clojure的defn是同樣樣的.
例:
(s/defn deposite :- (s/maybe s/Int)
[order-id :- (s/maybe s/Int) pay-type :- s/Str]
...)
(1)假設想要對函數作類型檢查,必須使用schema中封裝的defn 或 fn來定義函數。這是運行類型檢查的基礎。但是是否進行類型檢查,還有「開關」進行控制。
(2)參數和返回值:可以用":-"符號來指定一個參數和返回值的類型(可以是本身定義類型)。
(3)假設數據可能爲nil時,可以用maybe函數來修飾。
(4)假設想要對某個函數或者多個函數進行類型檢查,可以用with-fn-validation來運行這些函數。如:
(s/with-fn-validation
(deposite 1 "yidong")
(function2 ...)
(function3 ...))
* 這個至關於類型檢查的「開關」,在測試代碼中很實用。
咱們可以在測試的時候開啓類型檢查。而公佈的時候則不需要開啓。
(5)假設想要一個函數老是運行類型檢查,可以使用「^:always-validate」。如:
(s/defn ^:always-validate finish-order :- Map
[order-id :- s/Int pay-type :- s/Str pay-result :- s/Bool]
*對於那些和用戶輸入相關的函數,可以使用該方法。
(1)可本身定義數據類型。
(2)可自由控制檢測開關。
比方,可在測試時打開類型檢測。公佈時關閉.
(3)明白輸入輸出, 提升代碼可讀性。
不需要爲函數參數和返回值寫一堆凝視:凝視和代碼不一樣步,天然語言描寫敘述的不明白、不一致,在每個使用該數據的地方都要寫一次凝視.
(1)不能對數組的個數作限定,假設想定義僅僅有兩個元素的數組"[Long Long]".
我的想法:這不能算是不足。因爲schema主要是作類型檢測的,不是編譯器。
(2)不能定義某些複雜的類型。如想要給如下的數據結構定義一個類型:
[[1 1.0] [2 2.0]]
你可能會定義成:
(def a [[s/Int double]])
結果執行(s/validate a [[1 1.0] [2 2.0]])出錯.
定義成[[s/Num]]則執行正常.
我的想法:數組中存放的元素的類型應該是一致的(C/C++/JAVA等語言中,數組中元素的類型不都是一致的麼?), 你可以把它們封裝在一個map或者類裏。再來定義。
文檔上說是1.5.1 and 1.6.x,實際測試發現1.7.0-alpha也支持。
*還支持ClojureScript(有需要的時候再研究,歡迎你們補充).
以上是依據我的實踐和查閱資料所總結出來的, 有不足或者錯誤之處,請你們補充和指正.