schema for clojure

Schema for Clojure Data Shape

Declaration and Validation


1.何爲schema

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:...工具


2.schema在clojure中的使用

(1)project.clj的:dependencies中加入「[prismatic/schema "0.3.1"]」包。ui

(2)在命名空間的:require中增長「[schema.core :as s]」。spa


3.定義數據類型

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


4.定義變量

可以用schema.core中的def來定義一個變量, 如:

(s/def foo :- long 2)

要求用於變量初始化的值必須知足定義的schema.


5.定義函數

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]

       *對於那些和用戶輸入相關的函數,可以使用該方法。


6.schema的優勢:

(1)可本身定義數據類型。

(2)可自由控制檢測開關。

         比方,可在測試時打開類型檢測。公佈時關閉.

(3)明白輸入輸出, 提升代碼可讀性。

         不需要爲函數參數和返回值寫一堆凝視:凝視和代碼不一樣步,天然語言描寫敘述的不明白、不一致,在每個使用該數據的地方都要寫一次凝視.


7.schema的不足:

(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或者類裏。再來定義。


8.schema支持的clojure版本號。

文檔上說是1.5.1 and 1.6.x,實際測試發現1.7.0-alpha也支持。

*還支持ClojureScript(有需要的時候再研究,歡迎你們補充).



以上是依據我的實踐和查閱資料所總結出來的, 有不足或者錯誤之處,請你們補充和指正.

相關文章
相關標籤/搜索