Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
clojure.specの話(仮)
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
OHTA Shogo
July 21, 2016
380
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
clojure.specの話(仮)
OHTA Shogo
July 21, 2016
More Decks by OHTA Shogo
See All by OHTA Shogo
テンクーでのClojure活用事例
athos
0
420
軽量デバッグツールPostmortemの紹介.pdf
athos
1
210
Clojure 1.10 概要紹介
athos
3
700
やってみる!clojure.spec
athos
4
1.1k
kitchen-async: a promising (?) Promise library, or a poor man's core.async
athos
3
510
Clojure 1.9 概要紹介
athos
4
1.5k
ここ最近のClojureScript
athos
5
1.8k
(= ? (+ nREPL Docker))
athos
0
590
clojure.specの話
athos
3
2.4k
Featured
See All Featured
Typedesign – Prime Four
hannesfritz
42
3.1k
Building Adaptive Systems
keathley
44
3.2k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
710
Code Review Best Practice
trishagee
74
20k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
490
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
430
Building Applications with DynamoDB
mza
96
7.2k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
630
Speed Design
sergeychernyshev
33
2k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
750
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
420
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
240
Transcript
DMPKVSFTQFDͷ Ծ OJTIJTIJOKVDMPKVSF !BUIPT
ࣗݾհ ‣ 5XJUUFS!BUIPT ‣ χϟϯύεגࣜձࣾॴଐ ‣ $MPKVSFίϯτϦϏϡʔλ
ૣͰ͕͢
$MPKVSFͷҰ൪ ϜΧͭ͘ͱ͜Ζͬͯʁ
Τϥʔϝοηʔδ ࠾༻ εΫϦϓτΛ࡞Δ͠͞ υΩϡϝϯτɾνϡʔτϦΞϧ ੩తܕ͕ͳ͍ $MPKVSFTVSWFZʮ$MPKVSFͷҰ൪ϜΧͭ͘ͱ͜Ζʁʯ
Τϥʔϝοηʔδ
‣ $MPKVSFͷΤϥʔͷ͔Γʹ͘͞Α͘ࢦఠ͞ΕΔ ‣ $MPKVSFͷࠐΈؔͷଟ͘ΨʔϕδΠϯΨʔϕδ Ξτ ‣ ҾνΣοΫΛೖΕΔͱɺ+*5ίϯύΠϥͷ࠷దԽΛ ્͠ɺύϑΥʔϚϯεʹӨڹ͢ΔͨΊ
Կ͕ωοΫ͔ʁ ‣ ύϑΥʔϚϯε໘͔Βߟ͑Δͱ࣮ߦ࣌ͷνΣοΫ ۃྗආ͚͍ͨ ‣ ͔͠͠ɺ੩తܕ͕ͳ͍Ҏ্ίϯύΠϧ͚࣌ͩͰνΣο Ϋ͖͠Δͷ͍͠ ‣ ։ൃ͚࣌ͩΦϯʹͰ͖ΔҾνΣοΫͷΈ͕͋ Ε͍͍
DMPKVSFTQFD
DMPKVSFTQFD ‣ ࣍ظϦϦʔε$MPKVSFͰͷಋೖ͕ਐΊΒΕ͍ͯΔ৽ػೳ ‣ ੩తܕͰͳ͘ɺड़ޠͷΈ߹ΘͤʹΑͬͯσʔλܕͷ༷ Λهड़͢Δ ‣ Ұ༷ εϖοΫ Λॻ͚ҰཻͰԿ͓͍͍͠
υΩϡϝϯςʔγϣϯ ܖϓϩάϥϛϯά ϓϩύςΟϕʔεςετ ϚΫϩͷߏจνΣοΫ
DMPKVSFTQFDͷ͍ํ ‣ [org.clojure/clojure “1.9.0-alphaXX”] Λ:dependenciesʹՃ ‣ ࠷৽൛BMQIB ݱࡏ ‣
(require ‘[clojure.spec :as s])
DMPKVSFTQFDೖ
ड़ޠ ‣ ड़ޠ CPPMΛฦؔ͢ ͦͷ··ͰεϖοΫͱͯ͠ ͑Δ user=> (s/valid? integer? 42)
true user=> (s/valid? integer? “foo”) false
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
εϖοΫͷ߹ ‣ BOEPSΛͬͯෳͷεϖοΫΛΈ߹ΘͤՄೳ 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
εϖοΫʹ໊લΛ͚ͭΔ ‣ 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
ίϨΫγϣϯͷεϖοΫ ‣ 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
ίϨΫγϣϯͷεϖοΫ ‣ ΩʔʹΑͬͯͷܕ͕ҧ͏ϚοϓͷεϖοΫఆٛՄೳ 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
DMPKVSFTQFDʹΑΔ ܖϓϩάϥϛϯά
ܖϓϩάϥϛϯάͱ ‣ ؔͷݺͼग़͠ʹؔͯ͠ɺࣄલ݅ɾࣄޙ݅ɾෆ ม݅ΛܾΊɺݺͼग़͢ଆͱݺͼग़͞ΕΔଆͷٛ Λ໌֬ʹ͢Δख๏ ݺͼग़͢ଆɿ ؔΛݺͼग़͢લʹࣄલ݅ͱෆม݅Λຬͨٛ͢Λෛ͏ ݺͼग़͞Εͨଆɿ
͔ؔΒͬͨޙʹࣄޙ݅ͱෆม݅Λຬͨٛ͢Λෛ͏
ؔʹର͢ΔεϖοΫ ‣ 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))
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=>
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=>
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=> Ͱݺͼग़ͨ͠ͱ͖ʹ ࣦഊ͢Δ͜ͱΛݕग़
DMPKVSFTQFDʹΑΔ ϓϩύςΟϕʔεςετ
ϓϩύςΟϕʔεςετͱ ‣ ී௨ͷςετ FYBNQMFCBTFEUFTUJOH ͷΑ͏ʹɺ ۩ମతͳςετέʔεʹର͢ΔςετͰͳ͘ɺ ҙͷೖྗʹରͯ͠Γཱͭੑ࣭Λهड़ͨ͠ςετ ‣ ೖྗͷϥϯμϜʹͨ͘͞Μੜ͠ɺͦͷʹର͠ ͯςετΛ࣮ߦ͢Δ
‣ )BTLFMMͷ2VJDL$IFDL͕༗໊ ‣ $MPKVSFͰUFTUDIFDLΛ͏ͷ͕ελϯμʔυ
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)))))
·ͱΊ ‣ DMPKVSFTQFDσʔλܕؔͷ༷Λड़ޠͷΈ ߹ΘͤͰهड़͢Δํ๏Λఏڙ͢Δ ‣ ҰεϖοΫΛॻ͘ͱɺίʔσΟϯάத͚ͩͰͳ͘ɺ υΩϡϝϯςʔγϣϯςετʹཱͯΒΕΔ ‣ $MPKVSFͷࠐΈؔʹର͢ΔεϖοΫ͕༻ҙ͞Ε ΕΤϥʔϝοηʔδվળ͞ΕΔ͔ʁ
ࠓ͞ͳ͔ͬͨ͜ͱ ‣ TDPOGPSN ‣ γʔέϯεʹର͢ΔεϖοΫ ‣ εϖοΫʹΑΔϚΫϩͷߏจղੳ ଓ͖ͷ-JTQNFFUVQͰʂʂ