Upgrade to Pro — share decks privately, control downloads, hide ads and more …

clojure.specの話(仮)

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for OHTA Shogo OHTA Shogo
July 21, 2016
360

 clojure.specの話(仮)

Avatar for OHTA Shogo

OHTA Shogo

July 21, 2016
Tweet

Transcript

  1. WBMJE FYQMBJO ‣ WBMJE ͸εϖοΫΛຬ͔ͨ͢Ͳ͏͔Λฦ͢ ‣ FYQMBJO͸εϖοΫΛຬͨ͞ͳ͍ՕॴΛࢦఠ͢Δ user=> (s/valid? integer?

    “foo”) false user=> (s/explain integer? “foo”) val: "foo" fails predicate: :clojure.spec/unknown nil user=> (s/explain integer? 42) Success! nil
  2. εϖοΫͷ߹੒ ‣ BOE΍PSΛ࢖ͬͯෳ਺ͷεϖοΫΛ૊Έ߹ΘͤՄೳ user=> (s/valid? (s/and integer? even?) 0) true

    user=> (s/valid? (s/and integer? even?) 1) false user=> (s/valid? (s/or :int integer? :str string?) “foo”) true
  3. εϖοΫʹ໊લΛ͚ͭΔ ‣ EFGͰεϖοΫʹ໊લΛ͚ͭΔ͜ͱ͕Ͱ͖Δ ‣ εϖοΫࣗମΛ࠶ར༻Ͱ͖Δ user=> (s/def ::answer-to-everything (fn [x]

    (= x 42)) :user/answer-to-everything user=> (s/valid? ::answer-to-everything 43) false user=> (s/valid? ::answer-to-everything 42) true
  4. ίϨΫγϣϯͷεϖοΫ ‣ coll-ofmap-ofͰίϨΫγϣϯͷཁૉ͕εϖοΫ Λຬ͍ͨͯ͠Δ͔νΣοΫͰ͖Δ user=> (s/valid? (s/coll-of integer?) [1 2

    3]) true user=> (s/valid? (s/coll-of integer?) [1 :a]) false user=> (s/valid? (s/map-of keyword? integer?) {:a 0, :b 1}) true user=> (s/valid? (s/map-of keyword? integer?) {:a 0, :b “foo”}) false
  5. ίϨΫγϣϯͷεϖοΫ ‣ ΩʔʹΑͬͯ஋ͷܕ͕ҧ͏ϚοϓͷεϖοΫ΋ఆٛՄೳ user=> (s/def ::x integer?) :user/x user=> (s/def

    ::y string?) :user/y user=> (s/explain (s/keys :req-un [::x ::y]) {:x 1, :y 2}) In: [:y] val: 2 fails spec: :user/y at: [:y] predicate: string? nil user=> (s/valid? (s/keys :req-un [::x ::y]) {:x 1, :y “foo”}) true
  6. ؔ਺ʹର͢ΔεϖοΫ ‣ fizzbuzzؔ਺ͷεϖοΫ͸্ͷΑ͏ʹఆٛͰ͖Δ ‣ :args :ret͕ͦΕͧΕࣄલ৚݅ɾࣄޙ৚݅ʹରԠ (s/fdef fizzbuzz :args (s/cat

    :n (s/and integer? #(> % 0))) :ret (s/or :int integer? :key keyword?)) (defn fizzbuzz [n] (cond (= (mod n 15) 0) :fizzbuzz (= (mod n 5) 0) :buzz (= (mod n 3) 0) “fizz” ;;←όά :else n))
  7. JOTUSVNFOU ‣ ؔ਺ʹҾ਺͕εϖοΫΛຬ͍ͨͯ͠Δ͔ͷνΣοΫ ΛΦϯɾΦϑͰ͖Δ user=> (require ‘[clojure.spec.test :as t]) nil

    user=> (t/instrument) [user/fizzbuzz] user=> (fizzbuzz 15) “fizzbuzz” user=> (fizzbuzz “foo”) ExceptionInfo Call to #'user/fizzbuzz did not conform to spec: In: [0] val: "foo" fails at: [:args :n] predicate: integer? :clojure.spec/args ("foo") … user=>
  8. DIFDL ‣ Ҿ਺ͷεϖοΫΛຬͨ͢஋Λࣗಈੜ੒ͯ͠ɺͦͷ஋Λؔ਺ʹ ౉ͨ݁͠Ռ͕໭Γ஋ͷεϖοΫΛຬ͔ͨ͢νΣοΫ͢Δ user=> (t/check) ({:spec … :clojure.spec.test.check/ret {:result

    #error {:cause "Specification-based check failed” :data {:clojure.spec/problems (… {:path [:ret :key], :pred keyword?, :val “fizz", :via [], :in [], :clojure.spec.test/args (3), :clojure.spec/failure :check-failed}…)} user=>
  9. DIFDL ‣ Ҿ਺ͷεϖοΫΛຬͨ͢஋Λࣗಈੜ੒ͯ͠ɺͦͷ஋Λؔ਺ʹ ౉ͨ݁͠Ռ͕໭Γ஋ͷεϖοΫΛຬ͔ͨ͢νΣοΫ͢Δ user=> (t/check) ({:spec … :clojure.spec.test.check/ret {:result

    #error {:cause "Specification-based check failed” :data {:clojure.spec/problems (… {:path [:ret :key], :pred keyword?, :val “fizz", :via [], :in [], :clojure.spec.test/args (3), :clojure.spec/failure :check-failed}…)} user=> Ͱݺͼग़ͨ͠ͱ͖ʹ ࣦഊ͢Δ͜ͱΛݕग़
  10. p[[CV[[ؔ਺ͷςετ ‣ εϖοΫΛຬͨ͢஋Λࣗಈੜ੒͠ɺ͢΂ͯͷ஋ʹର ͯ͠ੑ࣭͕੒Γཱ͔ͭͲ͏͔νΣοΫ͢Δ (ns fizzbuzz-test (:require [clojure.test.check.clojure-test :refer [defspec]]

    [clojure.test.check.properties :as prop] [clojure.spec :as s] [fizzbuzz :as fb])) (defspec fizzbuzz-prop (prop/for-all [n (s/gen (s/and integer? #(> % 0)))] (let [v (fb/fizzbuzz n)] (cond (= (mod n 3) 0) (contains? #{:fizz :fizzbuzz} v) (= (mod n 5) 0) (contains? #{:buzz :fizzbuzz} v) :else (= n v)))))