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(有需要的时候再研究,欢迎你们补充).
以上是依据我的实践和查阅资料所总结出来的, 有不足或者错误之处,请你们补充和指正.