Clojure spec
用途
定义、校验数据的结构,并生成数据
引入
# project.clj
[org.clojure/clojure "1.11.1"]
# head
(require '[clojure.spec.alpha :as s])
# or
(ns my.ns (:require [clojure.spec.alpha :as s]))
函数
断言
是否符合规范
(s/conform even? 1000)
=> 1000
(s/conform even? 1001)
=> :clojure.spec.alpha/invalid
(s/vaild? even? 10)
=> true
(s/vaild? even? 11)
=> false
注册
定义规范
(s/def :order/date inst?)
(s/def :deck/suit #{:club :diamond :heart :spade})
(s/valid? :order/date (Date.))
;;=> true
(s/conform :deck/suit :club)
;;=> :club
组合规范
- s/and 组合同时达成的断言
s/or 组合任意达成的断言
(s/def :num/big-even (s/and int? even? #(> % 1000))) (s/valid? :num/big-even :foo) ;; false (s/valid? :num/big-even 10) ;; false (s/valid? :num/big-even 100000) ;; true (s/def :domain/name-or-id (s/or :name string? :id int?)) (s/valid? :domain/name-or-id "abc") ;; true (s/valid? :domain/name-or-id 100) ;; true (s/valid? :domain/name-or-id :foo) ;; false (s/conform :domain/name-or-id "abc") ;;=> [:name "abc"] (s/conform :domain/name-or-id 100) ;;=> [:id 100] ; for nil problem (s/valid? string? nil) ;;=> false (s/valid? (s/nilable string?) nil) ;;=> true
追溯原因
(s/explain :deck/suit 42)
;; 42 - failed: #{:spade :heart :diamond :club} spec: :deck/suit
(s/explain :num/big-even 5)
;; 5 - failed: even? spec: :num/big-even
(s/explain :domain/name-or-id :foo)
;; :foo - failed: string? at: [:name] spec: :domain/name-or-id
;; :foo - failed: int? at: [:id] spec: :domain/name-or-id
键值规范
clojure.spec.alpha的s/keys方法是用于创建和返回一个验证map的规范。它接受以下参数:
:req:一个包含必须存在的键的向量,键必须是命名空间限定的关键字
:opt:一个包含可选存在的键的向量,键必须是命名空间限定的关键字
:req-un:一个包含必须存在但不需要命名空间限定的键的向量
:opt-un:一个包含可选存在但不需要命名空间限定的键的向量
:gen:一个函数,用于生成符合规范的map
(s/def ::even integer? even?)
(s/def ::odd integer? odd?)
(s/valid? (s/coll-of ::even) [2 4 6]) ; true
(s/valid? (s/tuple ::even ::odd) [2 3]) ; true
(s/valid? (s/cat :e1 ::even :o1 ::odd) [2 3]) ; true
(s/valid? (s/alt :e1 ::even :o1 ::odd) [2]) ; true
(s/def :unq/person
(s/keys :req-un [:acct/first-name :acct/last-name :acct/email]
:opt-un [:acct/phone]))
;不需要命名空间限定
(s/conform :unq/person
{:first-name "Bugs" :last-name "Bunny" :email "bugs@example.com"})
;;=> {:first-name "Bugs", :last-name "Bunny", :email "bugs@example.com"}
:: 语法糖
::在clojure.spec.alpha里是一个语法糖,用于表示当前命名空间下的一个规范名称。例如,如果当前命名空间是my.ns,那么::foo就相当于:my.ns/foo。这样可以避免重复输入命名空间的前缀,也可以避免规范名称的冲突。例如:
专注于为企业提供从需求分析到系统实施的全流程信息化建设服务。
http://mip.jadxl.cn/