Skip to content

Instantly share code, notes, and snippets.

@lagenorhynque
Last active September 21, 2017 15:05
Show Gist options
  • Select an option

  • Save lagenorhynque/55455c5ca5c7d95607f88b1e53d25bdd to your computer and use it in GitHub Desktop.

Select an option

Save lagenorhynque/55455c5ca5c7d95607f88b1e53d25bdd to your computer and use it in GitHub Desktop.
clojure.spec vs core.typed vs schema
;; cf. https://clojure.org/guides/spec
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (s/def ::side-a number?)
:user/side-a
user=> (s/def ::side-b number?)
:user/side-b
user=> (s/def ::side-c number?)
:user/side-c
user=> (s/fdef cuboid-volume
#_=> :args (s/cat :cuboid (s/keys :req [::side-a ::side-b ::side-c]))
#_=> :ret number?)
user/cuboid-volume
user=> (defn cuboid-volume [{::keys [side-a side-b side-c]}]
#_=> (* side-a side-b side-c))
#'user/cuboid-volume
user=> (require '[clojure.spec.test.alpha :as stest])
nil
user=> (stest/instrument)
[user/cuboid-volume]
user=> (cuboid-volume #::{:side-a 1 :side-b 2 :side-c 3})
6
user=> (cuboid-volume #::{:side-a 1 :side-b "2" :side-c 3})
ExceptionInfo Call to #'user/cuboid-volume did not conform to spec:
In: [0 :user/side-b] val: "2" fails spec: :user/side-b at: [:args :cuboid :user/side-b] predicate: number?
:clojure.spec.alpha/spec #object[clojure.spec.alpha$regex_spec_impl$reify__1200 0x6851982e "clojure.spec.alpha$regex_spec_impl$reify__1200@6851982e"]
:clojure.spec.alpha/value (#:user{:side-a 1, :side-b "2", :side-c 3})
:clojure.spec.alpha/args (#:user{:side-a 1, :side-b "2", :side-c 3})
:clojure.spec.alpha/failure :instrument
:clojure.spec.test.alpha/caller {:file "form-init4503318645991203844.clj", :line 1, :var-scope user/eval763}
clojure.core/ex-info (core.clj:4744)
user=> (cuboid-volume #::{:side-a 1 :side-d 2 :side-c 3})
ExceptionInfo Call to #'user/cuboid-volume did not conform to spec:
In: [0] val: #:user{:side-a 1, :side-d 2, :side-c 3} fails at: [:args :cuboid] predicate: (contains? % :user/side-b)
:clojure.spec.alpha/spec #object[clojure.spec.alpha$regex_spec_impl$reify__1200 0x6851982e "clojure.spec.alpha$regex_spec_impl$reify__1200@6851982e"]
:clojure.spec.alpha/value (#:user{:side-a 1, :side-d 2, :side-c 3})
:clojure.spec.alpha/args (#:user{:side-a 1, :side-d 2, :side-c 3})
:clojure.spec.alpha/failure :instrument
:clojure.spec.test.alpha/caller {:file "form-init4503318645991203844.clj", :line 1, :var-scope user/eval765}
clojure.core/ex-info (core.clj:4744)
user=> (cuboid-volume #::{:side-a 1 :side-c 3})
ExceptionInfo Call to #'user/cuboid-volume did not conform to spec:
In: [0] val: #:user{:side-a 1, :side-c 3} fails at: [:args :cuboid] predicate: (contains? % :user/side-b)
:clojure.spec.alpha/spec #object[clojure.spec.alpha$regex_spec_impl$reify__1200 0x6851982e "clojure.spec.alpha$regex_spec_impl$reify__1200@6851982e"]
:clojure.spec.alpha/value (#:user{:side-a 1, :side-c 3})
:clojure.spec.alpha/args (#:user{:side-a 1, :side-c 3})
:clojure.spec.alpha/failure :instrument
:clojure.spec.test.alpha/caller {:file "form-init4503318645991203844.clj", :line 1, :var-scope user/eval767}
clojure.core/ex-info (core.clj:4744)
user=>
;; cf. https://github.com/clojure/core.typed
user=> (require '[clojure.core.typed :as t])
nil
user=> (alter-meta! *ns* assoc :lang :core.typed)
{:lang :core.typed}
user=> (t/ann cuboid-volume [(t/HMap :mandatory {:side-a t/Num :side-b t/Num :side-c t/Num}) :-> t/Num])
nil
user=> (defn cuboid-volume [{:keys [side-a side-b side-c]}]
#_=> (* side-a side-b side-c))
#'user/cuboid-volume
user=> (t/install)
Initializing core.typed ...
Building core.typed base environments ...
Finished building base environments
"Elapsed time: 5431.748305 msecs"
core.typed initialized.
nil
user=> (cuboid-volume {:side-a 1 :side-b 2 :side-c 3})
6
user=> (cuboid-volume {:side-a 1 :side-b "2" :side-c 3})
Type Error (/private/var/folders/pb/09r355mn7nl2b0pcgdjg9vdh0000gn/T/form-init6733062574805230267.clj:1:1) Function user/cuboid-volume could not be applied to arguments:
Domains:
(t/HMap :mandatory {:side-a t/Num, :side-b t/Num, :side-c t/Num})
Arguments:
(t/HMap :mandatory {:side-a (t/Val 1), :side-b (t/Val "2"), :side-c (t/Val 3)} :complete? true)
Ranges:
t/Num
in: (user/cuboid-volume {:side-a 1, :side-b "2", :side-c 3})
ExceptionInfo Type Checker: Found 1 error clojure.core/ex-info (core.clj:4744)
user=> (cuboid-volume {:side-a 1 :side-d 2 :side-c 3})
Type Error (/private/var/folders/pb/09r355mn7nl2b0pcgdjg9vdh0000gn/T/form-init6733062574805230267.clj:1:1) Function user/cuboid-volume could not be applied to arguments:
Domains:
(t/HMap :mandatory {:side-a t/Num, :side-b t/Num, :side-c t/Num})
Arguments:
(t/HMap :mandatory {:side-a (t/Val 1), :side-d (t/Val 2), :side-c (t/Val 3)} :complete? true)
Ranges:
t/Num
in: (user/cuboid-volume {:side-a 1, :side-d 2, :side-c 3})
ExceptionInfo Type Checker: Found 1 error clojure.core/ex-info (core.clj:4744)
user=> (cuboid-volume {:side-a 1 :side-c 3})
Type Error (/private/var/folders/pb/09r355mn7nl2b0pcgdjg9vdh0000gn/T/form-init6733062574805230267.clj:1:1) Function user/cuboid-volume could not be applied to arguments:
Domains:
(t/HMap :mandatory {:side-a t/Num, :side-b t/Num, :side-c t/Num})
Arguments:
(t/HMap :mandatory {:side-a (t/Val 1), :side-c (t/Val 3)} :complete? true)
Ranges:
t/Num
in: (user/cuboid-volume {:side-a 1, :side-c 3})
ExceptionInfo Type Checker: Found 1 error clojure.core/ex-info (core.clj:4744)
user=>
;; cf. https://github.com/plumatic/schema
user=> (require '[schema.core :as s])
nil
user=> (s/set-fn-validation! true)
nil
user=> (s/defn cuboid-volume :- s/Num
#_=> [{:keys [side-a side-b side-c]} :- {:side-a s/Num
#_=> :side-b s/Num
#_=> :side-c s/Num}]
#_=> (* side-a side-b side-c))
#'user/cuboid-volume
user=> (cuboid-volume {:side-a 1 :side-b 2 :side-c 3})
6
user=> (cuboid-volume {:side-a 1 :side-b "2" :side-c 3})
ExceptionInfo Input to cuboid-volume does not match schema:
[(named {:side-b (not (instance? java.lang.Number "2"))} arg0)]
user/eval2595/cuboid-volume--2600 (form-init3164367379734419919.clj:1)
user=> (cuboid-volume {:side-a 1 :side-d 2 :side-c 3})
ExceptionInfo Input to cuboid-volume does not match schema:
[(named {:side-b missing-required-key, :side-d disallowed-key} arg0)]
user/eval2595/cuboid-volume--2600 (form-init3164367379734419919.clj:1)
user=> (cuboid-volume {:side-a 1 :side-c 3})
ExceptionInfo Input to cuboid-volume does not match schema:
[(named {:side-b missing-required-key} arg0)]
user/eval2595/cuboid-volume--2600 (form-init3164367379734419919.clj:1)
user=>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment