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 29, 2016
Programming
3
2.3k
clojure.specの話
2016/07/29 Lisp meetup #42 の発表資料です。
OHTA Shogo
July 29, 2016
Tweet
Share
More Decks by OHTA Shogo
See All by OHTA Shogo
テンクーでのClojure活用事例
athos
0
300
軽量デバッグツールPostmortemの紹介.pdf
athos
1
190
Clojure 1.10 概要紹介
athos
3
620
やってみる!clojure.spec
athos
4
990
kitchen-async: a promising (?) Promise library, or a poor man's core.async
athos
3
450
Clojure 1.9 概要紹介
athos
4
1.4k
ここ最近のClojureScript
athos
5
1.7k
(= ? (+ nREPL Docker))
athos
0
510
clojure.specの話(仮)
athos
2
340
Other Decks in Programming
See All in Programming
Flutter × Firebase Genkit で加速する生成 AI アプリ開発
coborinai
0
160
PHPのバージョンアップ時にも役立ったAST
matsuo_atsushi
0
110
Immutable ActiveRecord
megane42
0
140
JavaScriptツール群「UnJS」を5分で一気に駆け巡る!
k1tikurisu
9
1.8k
ファインディLT_ポケモン対戦の定量的分析
fufufukakaka
0
730
Amazon ECS とマイクロサービスから考えるシステム構成
hiyanger
2
560
CDK開発におけるコーディング規約の運用
yamanashi_ren01
2
130
CI改善もDatadogとともに
taumu
0
120
苦しいTiDBへの移行を乗り越えて快適な運用を目指す
leveragestech
0
620
動作確認やテストで漏れがちな観点3選
starfish719
6
1k
Amazon Bedrock Multi Agentsを試してきた
tm2
1
290
Spring gRPC について / About Spring gRPC
mackey0225
0
220
Featured
See All Featured
GitHub's CSS Performance
jonrohan
1030
460k
Designing Experiences People Love
moore
140
23k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
10
1.3k
Statistics for Hackers
jakevdp
797
220k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
12
960
The Cost Of JavaScript in 2023
addyosmani
47
7.3k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
7.1k
Fontdeck: Realign not Redesign
paulrobertlloyd
83
5.4k
4 Signs Your Business is Dying
shpigford
182
22k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Navigating Team Friction
lara
183
15k
A Philosophy of Restraint
colly
203
16k
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