Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
clojure.specの話
Search
OHTA Shogo
July 29, 2016
Programming
2.4k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
clojure.specの話
2016/07/29 Lisp meetup #42 の発表資料です。
OHTA Shogo
July 29, 2016
More Decks by OHTA Shogo
See All by OHTA Shogo
テンクーでのClojure活用事例
athos
0
440
軽量デバッグツールPostmortemの紹介.pdf
athos
1
220
Clojure 1.10 概要紹介
athos
3
710
やってみる!clojure.spec
athos
4
1.1k
kitchen-async: a promising (?) Promise library, or a poor man's core.async
athos
3
520
Clojure 1.9 概要紹介
athos
4
1.6k
ここ最近のClojureScript
athos
5
1.8k
(= ? (+ nREPL Docker))
athos
0
610
clojure.specの話(仮)
athos
2
390
Other Decks in Programming
See All in Programming
Web3Dライブラリを作ってVue Custom Rendererの仕組みを理解しよう / lets learn vue custom renderer by making 3d library
drumath2237
1
120
Optunaを作ったときにやりたかったこと、その後 (2026/10/16, Optuna Meetup #3)
iwiwi
4
1.5k
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
410
느린 네트워크와 저사양 디바이스 사용자를 위한 웹뷰 로딩 시간 개선기
kmkim
1
190
AIで開発が速くなった先で、開発チームは何を目指すか
shihochan
1
2k
Kawaiicon: Kubernetes, it's no longer cool, but let's secure it anyway!
barnbarn
0
110
Vapor Mode でアクセシビリティは 壊れないか検証した話
fuqda
1
320
動画プレイヤーはなぜカクつくのか 〜Flutterのレンダリングとネイティブの境界を解剖する〜
naruogram
0
330
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
590
プロジェクトコードをキレイキレイしよう!暗黙的な参照を読み解く静的解析
ostk0069
0
200
学びを記事・スライド・Xへ高速展開する― AI-assisted Learning Loopで回すコンテンツ生成術
ochtum
0
190
Rails初心者がパスキーを実装してみて大変だったこと
ktombow
0
120
Featured
See All Featured
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
70
68k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
460
Accessibility Awareness
sabderemane
1
290
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
560
ラッコキーワード サービス紹介資料
rakko
5
5.7M
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
670
The browser strikes back
jonoalderson
0
1.9k
Mobile First: as difficult as doing things right
swwweet
225
10k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.4k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.8k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.7k
Transcript
DMPKVSFTQFDͷ -JTQNFFUVQ !BUIPT
ࣗݾհ ‣ 5XJUUFS!BUIPT ‣ χϟϯύεגࣜձࣾॴଐ ‣ $MPKVSFίϯτϦϏϡʔλ
DMPKVSFTQFD ‣ ࣍ظϦϦʔεͰͷಋೖ͕ਐΊΒΕ͍ͯΔ৽ػೳ ‣ ੩తܕͰͳ͘ɺड़ޠͷΈ߹ΘͤʹΑͬͯσʔλ ܕɾؔͷ༷Λهड़͢Δ ‣ Ұ༷ εϖοΫ Λॻ͚ҰཻͰԿ͓͍͍͠
υΩϡϝϯςʔγϣϯ ܖϓϩάϥϛϯά ϓϩύςΟϕʔεςετ ϚΫϩͷߏจνΣοΫ
DMPKVSFTQFDͷ͍ํ ‣ [org.clojure/clojure “1.9.0-alphaXX”] Λ:dependenciesʹՃ ‣ ࠷৽൛BMQIB ݱࡏ ‣
(require ‘[clojure.spec :as s])
όϦσʔλͱͯ͠ͷ DMPKVSFTQFD
ड़ޠ ‣ ड़ޠ CPPMΛฦؔ͢ ͦͷ··ͰεϖοΫͱͯ͠ ͑Δ user=> (s/valid? integer? 42)
ड़ޠ ‣ ड़ޠ CPPMΛฦؔ͢ ͦͷ··ͰεϖοΫͱͯ͠ ͑Δ user=> (s/valid? integer? 42)
true user=> (s/valid? integer? “foo”)
ड़ޠ ‣ ड़ޠ CPPMΛฦؔ͢ ͦͷ··ͰεϖοΫͱͯ͠ ͑Δ user=> (s/valid? integer? 42)
true user=> (s/valid? integer? “foo”) false user=>
WBMJE FYQMBJO ‣ valid?εϖοΫΛຬ͔ͨ͢Ͳ͏͔Λฦ͢ ‣ explainεϖοΫΛຬͨ͞ͳ͍ՕॴΛࢦఠ͢Δ user=> (s/valid? integer? “foo”)
false user=> (s/explain integer? “foo”)
WBMJE FYQMBJO ‣ valid?εϖοΫΛຬ͔ͨ͢Ͳ͏͔Λฦ͢ ‣ explainεϖοΫΛຬͨ͞ͳ͍ՕॴΛࢦఠ͢Δ user=> (s/valid? integer? “foo”)
false user=> (s/explain integer? “foo”) val: "foo" fails predicate: :clojure.spec/unknown nil user=> (s/explain integer? 42)
WBMJE FYQMBJO ‣ valid?εϖοΫΛຬ͔ͨ͢Ͳ͏͔Λฦ͢ ‣ explainεϖοΫΛຬͨ͞ͳ͍ՕॴΛࢦఠ͢Δ 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 user=>
εϖοΫͷ߹ ‣ andorΛͬͯෳͷεϖοΫΛΈ߹ΘͤՄೳ user=> (s/valid? (s/and integer? even?) 0) true
user=> (s/valid? (s/and integer? even?) 1) false
εϖοΫͷ߹ ‣ andorΛͬͯෳͷεϖοΫΛΈ߹ΘͤՄೳ 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”)
εϖοΫͷ߹ ‣ andorΛͬͯෳͷεϖοΫΛΈ߹ΘͤՄೳ 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 user=>
εϖοΫʹ໊લΛ͚ͭΔ ‣ defͰεϖοΫʹ໊લΛ͚ͭΔ͜ͱ͕Ͱ͖Δ ‣ εϖοΫࣗମΛ࠶ར༻Ͱ͖Δ user=> (s/def ::answer-to-everything (fn [x]
(= x 42)) :user/answer-to-everything user=> (s/valid? ::answer-to-everything 43)
εϖοΫʹ໊લΛ͚ͭΔ ‣ defͰεϖοΫʹ໊લΛ͚ͭΔ͜ͱ͕Ͱ͖Δ ‣ εϖοΫࣗମΛ࠶ར༻Ͱ͖Δ 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)
εϖοΫʹ໊લΛ͚ͭΔ ‣ defͰεϖοΫʹ໊લΛ͚ͭΔ͜ͱ͕Ͱ͖Δ ‣ εϖοΫࣗମΛ࠶ར༻Ͱ͖Δ 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 user=>
ίϨΫγϣϯͷεϖοΫ ‣ coll-ofmap-ofͰίϨΫγϣϯͷཁૉ͕εϖοΫ Λຬ͍ͨͯ͠Δ͔νΣοΫͰ͖Δ user=> (s/valid? (s/coll-of integer?) [1 2
3])
ίϨΫγϣϯͷεϖοΫ ‣ coll-ofmap-ofͰίϨΫγϣϯͷཁૉ͕εϖοΫ Λຬ͍ͨͯ͠Δ͔νΣοΫͰ͖Δ user=> (s/valid? (s/coll-of integer?) [1 2
3]) true user=> (s/valid? (s/coll-of integer?) [1 :a])
ίϨΫγϣϯͷεϖοΫ ‣ 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})
ίϨΫγϣϯͷεϖοΫ ‣ 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”})
ίϨΫγϣϯͷεϖοΫ ‣ 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=>
ίϨΫγϣϯͷεϖοΫ ‣ ΩʔʹΑͬͯͷܕ͕ҧ͏ϚοϓͷεϖοΫఆٛՄೳ 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})
ίϨΫγϣϯͷεϖοΫ ‣ ΩʔʹΑͬͯͷܕ͕ҧ͏ϚοϓͷεϖοΫఆٛՄೳ 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”})
ίϨΫγϣϯͷεϖοΫ ‣ ΩʔʹΑͬͯͷܕ͕ҧ͏ϚοϓͷεϖοΫఆٛՄೳ 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 user=>
%C$πʔϧͱͯ͠ͷ 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)
JOTUSVNFOU ‣ ؔʹҾ͕εϖοΫΛຬ͍ͨͯ͠Δ͔ͷνΣοΫ ΛΦϯɾΦϑͰ͖Δ user=> (require ’[clojure.spec.test :as t]) nil
user=> (t/instrument) [user/fizzbuzz] user=> (fizzbuzz 15)
JOTUSVNFOU ‣ ؔʹҾ͕εϖοΫΛຬ͍ͨͯ͠Δ͔ͷνΣοΫ ΛΦϯɾΦϑͰ͖Δ user=> (require ’[clojure.spec.test :as t]) nil
user=> (t/instrument) [user/fizzbuzz] user=> (fizzbuzz 15) “fizzbuzz” user=> (fizzbuzz “foo”)
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)
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
HFO ‣ εϖοΫ͔ΒUFTUDIFDL༻ͷδΣωϨʔλΛ࡞Δ ‣ εϖοΫΛຬͨ͢ϥϯμϜͳΛੜͰ͖Δ ‣ 3&1-Ͱαϯϓϧσʔλ͕΄͍͠ͱ͖ʹศར user=> (require ’[clojure.test.check.generators
:as gen]) nil user=> (gen/generate (s/gen (s/coll-of integer?)))
HFO ‣ εϖοΫ͔ΒUFTUDIFDL༻ͷδΣωϨʔλΛ࡞Δ ‣ εϖοΫΛຬͨ͢ϥϯμϜͳΛੜͰ͖Δ ‣ 3&1-Ͱαϯϓϧσʔλ͕΄͍͠ͱ͖ʹศར user=> (require ’[clojure.test.check.generators
:as gen]) nil user=> (gen/generate (s/gen (s/coll-of integer?))) [16719156 -26693 47] user=> (gen/generate (s/gen (s/coll-of integer?)))
HFO ‣ εϖοΫ͔ΒUFTUDIFDL༻ͷδΣωϨʔλΛ࡞Δ ‣ εϖοΫΛຬͨ͢ϥϯμϜͳΛੜͰ͖Δ ‣ 3&1-Ͱαϯϓϧσʔλ͕΄͍͠ͱ͖ʹศར user=> (require ’[clojure.test.check.generators
:as gen]) nil user=> (gen/generate (s/gen (s/coll-of integer?))) [16719156 -26693 47] user=> (gen/generate (s/gen (s/coll-of integer?))) [-158637744 -8 -461005 -238354 59127 -4365] user=>
HFOΛͬͨϓϩύςΟϕʔεςετ ‣ εϖοΫΛຬͨ͢Λࣗಈੜ͠ɺͯ͢ͷʹର ͯ͠ੑ࣭͕Γཱ͔ͭͲ͏͔νΣοΫ͢Δ (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)))))
ςετ࣮ߦ݁Ռ $ lein test
ςετ࣮ߦ݁Ռ $ lein test lein test fizzbuzz-test {:result false, :seed
1469711295643, :failing-size 4, :num- tests 5, :fail [96], :shrunk {:total-nodes-visited 6, :depth 5, :result false, :smallest [3]}, :test-var "fizzbuzz-prop"} lein test :only fizzbuzz-test/fizzbuzz-prop FAIL in (fizzbuzz-prop) (clojure_test.cljc:21) expected: result actual: false Ran 1 tests containing 1 assertions. 1 failures, 0 errors. Tests failed. $
ύʔαͱͯ͠ͷ DMPKVSFTQFD
γʔέϯεͷεϖοΫ SFHFY ‣ SFHFYͰཁૉͷฒͼʹରͯ͠εϖοΫΛఆٛͰ͖Δ user=> (s/valid? (s/* integer?) ’(1 2
3)) true user=> (s/valid? (s/alt :i integer? :s string?) ’(“foo”))
γʔέϯεͷεϖοΫ SFHFY ‣ SFHFYͰཁૉͷฒͼʹରͯ͠εϖοΫΛఆٛͰ͖Δ user=> (s/valid? (s/* integer?) ’(1 2
3)) true user=> (s/valid? (s/alt :i integer? :s string?) ’(“foo”)) true user=> (s/valid? (s/cat :i integer? :s string?) ’(1 “foo”))
γʔέϯεͷεϖοΫ SFHFY ‣ SFHFYͰཁૉͷฒͼʹରͯ͠εϖοΫΛఆٛͰ͖Δ user=> (s/valid? (s/* integer?) ’(1 2
3)) true user=> (s/valid? (s/alt :i integer? :s string?) ’(“foo”)) true user=> (s/valid? (s/cat :i integer? :s string?) ’(1 “foo”)) true user=> (s/valid? (s/cat :i* (s/* integer?) :s* (s/* string?)) ’(1 2 3 “foo” “bar”))
γʔέϯεͷεϖοΫ SFHFY ‣ SFHFYͰཁૉͷฒͼʹରͯ͠εϖοΫΛఆٛͰ͖Δ user=> (s/valid? (s/* integer?) ’(1 2
3)) true user=> (s/valid? (s/alt :i integer? :s string?) ’(“foo”)) true user=> (s/valid? (s/cat :i integer? :s string?) ’(1 “foo”)) true user=> (s/valid? (s/cat :i* (s/* integer?) :s* (s/* string?)) ’(1 2 3 “foo” “bar”)) true user=>
DPOGPSN ‣ εϖοΫʹ͕ͨͬͯ͠σʔλΛύʔε͢Δ ‣ ύʔεʹࣦഊͨ͠Β:clojure.spec/invalid͕ฦΔ user=> (s/conform (s/cat :i* (s/*
integer?) :s* (s/* string?)) ’(1 2 3 “foo” “bar”))
DPOGPSN ‣ εϖοΫʹ͕ͨͬͯ͠σʔλΛύʔε͢Δ ‣ ύʔεʹࣦഊͨ͠Β:clojure.spec/invalid͕ฦΔ user=> (s/conform (s/cat :i* (s/*
integer?) :s* (s/* string?)) ’(1 2 3 “foo” “bar”)) {:i* [1 2 3], :s* ["foo" "bar"]} user=> (s/conform (s/cat :i* (s/* integer?) :s* (s/* string?)) ’(1 2 “foo” 3 “bar”))
DPOGPSN ‣ εϖοΫʹ͕ͨͬͯ͠σʔλΛύʔε͢Δ ‣ ύʔεʹࣦഊͨ͠Β:clojure.spec/invalid͕ฦΔ user=> (s/conform (s/cat :i* (s/*
integer?) :s* (s/* string?)) ’(1 2 3 “foo” “bar”)) {:i* [1 2 3], :s* ["foo" "bar"]} user=> (s/conform (s/cat :i* (s/* integer?) :s* (s/* string?)) ’(1 2 “foo” 3 “bar”)) :clojure.spec/invalid user=>
ζϯυίΩϤγͷεϖοΫ (ns zundoko (:require [clojure.spec :as s])) (s/def ::zun*4-doko (s/cat
:1 ’#{ζϯ} :2 ’#{ζϯ} :3 ’#{ζϯ} :4 ’#{ζϯ} :5 ’#{υί})) (s/def ::has-no-zun*4-doko? (fn [xs] (every? #(not (s/valid? ::zun*4-doko %)) (partition 5 1 xs)))) (s/def ::zun-doko-kiyoshi (s/cat :preamble (s/& (s/* ’#{ζϯ υί}) ::has-no-zun*4-doko?) :zun*4-doko ::zun*4-doko :kiyoshi ’#{ΩϤγ}))
ζϯυίΩϤγͷεϖοΫ user=> (s/conform ::zun-doko-kiyoshi ’(υί ζϯ υί ζϯ ζϯ ζϯ
ζϯ υί ΩϤγ))
ζϯυίΩϤγͷεϖοΫ user=> (s/conform ::zun-doko-kiyoshi ’(υί ζϯ υί ζϯ ζϯ ζϯ
ζϯ υί ΩϤγ)) {:preamble [υί ζϯ υί], :zun*4-doko {:1 ζϯ, :2 ζϯ, :3 ζϯ, :4 ζϯ, :5 υί}, :kiyoshi ΩϤγ} user=> (s/explain ::zun-doko-kiyoshi ’(υί ζϯ υί ζϯ ζϯ ζϯ ζϯ υί))
ζϯυίΩϤγͷεϖοΫ user=> (s/conform ::zun-doko-kiyoshi ’(υί ζϯ υί ζϯ ζϯ ζϯ
ζϯ υί ΩϤγ)) {:preamble [υί ζϯ υί], :zun*4-doko {:1 ζϯ, :2 ζϯ, :3 ζϯ, :4 ζϯ, :5 υί}, :kiyoshi ΩϤγ} user=> (s/explain ::zun-doko-kiyoshi ’(υί ζϯ υί ζϯ ζϯ ζϯ ζϯ υί)) val: () fails spec: :zundoko/zun-doko-kiyoshi predicate: (alt), Insufficient input nil user=>
ϚΫϩͷߏจղੳ (s/def ::binding (s/cat :name simple-symbol? :init any?)) (s/def ::bindings
(s/and (s/* ::binding) vector?)) (s/def ::with-open (s/cat :bindings ::bindings :body (s/* any?)) (s/fdef with-open :args ::with-open :ret any?) user=> (s/conform ::with-open ’([in (open-file)] (slurp in))) {:bindings [{:name in, :init (open-file)}], :body [(slurp in)]} user=>
ϚΫϩͷߏจղੳ (defmacro with-open [bindings & body] (let [[binding & more]
(s/conform ::bindings bindings)] (if-not binding `(do ~@body) `(let ~[(:name binding) (:init binding)] (try (with-open ~(vec (s/unform ::bindings more)) ~@body) (finally (.close ~(:name binding)))))))) user=> (with-open [x] (slurp x)) ;;←ϚΫϩͷ͍ํΛޡΔ CompilerException java.lang.IllegalArgumentException: Call to intro-to-spec.macros/with-open did not conform to spec: In: [0] val: () fails spec: :intro-to-spec.macros/bindings at: [:args :bindings :init] predicate: any?, Insufficient input :clojure.spec/args ([x] (slurp x)) , compiling:(*cider-repl intro-to-spec*:1476:22) user=>
·ͱΊ ‣ DMPKVSFTQFDσʔλܕؔͷ༷Λड़ޠͷΈ ߹ΘͤͰهड़͢Δํ๏Λఏڙ͢Δ ‣ ҰεϖοΫΛॻ͘ͱɺؔͷόϦσʔγϣϯ͚ͩ Ͱͳ͘ɺ3&1-Ͱͷ։ൃ࣌ͷαϯϓϧσʔλੜ ςετɺϚΫϩͷύʔε͍Ζ͍Ζ͑Δ ‣ $MPKVSFʹ͓͚Δ։ൃͷํ͕େ͖͘มΘΔՄೳੑ
ͷ͋Δػೳ
ݱঢ়ʜ ‣ ·ͩBMQIBϦϦʔεͰ"1*͕มΘΓ·ͬͯ͘Δஈ֊ $MPKVSF4DSJQUͱͷฒΈଗͬͯͳ͍ ͷͰ࣮ઓ ೖΘΓͱݫ͍͠ هɿݱঢ়Ͱ$MPKVSFBMQIBͱ $MPKVSF4DSJQUͰ"1*Ϩϕϧͷޓੑ͕͋Δ༷ ‣
Τϥʔϝοηʔδใෆͷঢ়ଶղফ͞Ε͍ͯ Δ͕ɺݱঢ়ͰใաଟͰҰݟ͔ͯ͠Γʹ͍͘ ศརʹ͑ΔΑ͏ʹͳΔʹ։ൃڥଆͷαϙʔτඞཁ
ࢀߟจݙ ‣ DMPKVSFTQFD3BUJPOBMFBOE0WFSWJFX IUUQDMPKVSFPSHBCPVUTQFD ‣ TQFD(VJEF IUUQDMPKVSFPSHHVJEFTTQFD ‣ $PHOJDBTUDMPKVSFTQFDXJUI3JDI)JDLFZ IUUQCMPHDPHOJUFDUDPNDPHOJDBTU