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
OHTA Shogo
July 21, 2016
370
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
Mobile First: as difficult as doing things right
swwweet
225
10k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
Automating Front-end Workflow
addyosmani
1370
210k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
160
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.4k
WENDY [Excerpt]
tessaabrams
11
38k
Building Flexible Design Systems
yeseniaperezcruz
330
40k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Mind Mapping
helmedeiros
PRO
1
270
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
2
880
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
320
Typedesign – Prime Four
hannesfritz
42
3.1k
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Ͱʂʂ