狠狠撸

狠狠撸Share a Scribd company logo
Spectacular	Future
with	clojure.spec
Self-introduction
	/la?en????k/	カマイルカlagénorhynque
(defprofile lagénorhynque
:name "Kent OHASHI"
:languages [Clojure Haskell Python Scala
English fran?ais Deutsch русский]
:interests [programming language-learning mathematics]
:contributing [github.com/japan-clojurians/clojure-site-ja])
「颁濒辞箩耻谤别をプロダクトに导?した话」
Clojure
Contents
1.	 Clojure	Quick	Intro
2.	 New	Feature:	clojure.spec
Clojure	Quick	Intro
Clojure
Lisp
S式,	マクロ,	etc.
REPL駆動開発
関数型プログラミング?語
動的?語
JVM?語	(cf.	ClojureScript)
?	シンプルで強?な?語
リテラル
type example
string "abc"
character a
number 1,	2.0,	3N,	4.5M,	6/7,	8r10
boolean true,	false
nil nil
keyword :a,	:user/a,	::a,	::x/a
symbol 'a,	'user/a,	`a,	`x/a
type example
list '(1 2 3),	'(+ 1 2 3)
vector [1 2 3]
set #{1 2 3}
map {:a 1 :b 2},	#:user{:a 1 :b 2},
#::{:a 1 :b 2},	#::x{:a 1 :b 2}
function (fn [x] (* x x))
シンタックス
オペレータ
関数
マクロ
特殊形式
(op arg1 arg2 ... argn)
New	Feature:
clojure.spec
例:	直?体の体積計算
直?体の体積	=	辺a	×	辺b	×	辺c
user> (defn cuboid-volume [{:keys [side-a side-b side-c]}]
(* side-a side-b side-c))
#'user/cuboid-volume
user> (cuboid-volume {:side-a 1 :side-b 2 :side-c 3})
6
エラー
Javaのスタックトレースが\(^o^)/……
;; マップの値の型が数値ではなく?字列
user> (cuboid-volume {:side-a 1 :side-b "2" :side-c 3})
ClassCastException java.lang.String cannot be cast to java.lang.
Number clojure.lang.Numbers.multiply (Numbers.java:148)
;; マップのキー名でtypo
user> (cuboid-volume {:side-a 1 :side-d 2 :side-c 3})
NullPointerException clojure.lang.Numbers.ops (Numbers.java:10
18)
;; マップに必須のキーがない
user> (cuboid-volume {:side-a 1 :side-c 3})
NullPointerException clojure.lang.Numbers.ops (Numbers.java:10
18)
問題点
動的?語なのでコンパイル時に引数の型の不整合が
検出されない
少なくとも実?時に分かりやすいエラーになって
ほしい
マップのkey-valueに対するチェックがない
動的なデータを柔軟に表現したい
cf.	
漸進的型付け(gradual	typing)
Clojureに静的型システムを追加
コンパイル時に型チェック
core.typed
(require '[clojure.core.typed :as t])
(t/ann cuboid-volume [(t/HMap :mandatory {:side-a t/Num
:side-b t/Num
:side-c t/Num})
:-> t/Num])
(defn cuboid-volume [{:keys [side-a side-b side-c]}]
(* side-a side-b side-c))
cf.	
データ記述/バリデーションDSL
独?DSLでデータ構造を表現
実?時にバリデーション
schema
(require '[schema.core :as s])
(s/defn cuboid-volume :- s/Num
[{:keys [side-a side-b side-c]} :- {:side-a s/Num
:side-b s/Num
:side-c s/Num}]
(* side-a side-b side-c))
clojure.spec
述語(predicate)を組み合わせて仕様(spec)を書いて
ドキュメント
バリデーション
詳細なエラー報告
パースと分配束縛
データ?成
プロパティベーストテスト
などを実現する仕組み
dependency
REPL
[org.clojure/clojure "1.9.0-beta1"]
user> (require '[clojure.spec.alpha :as s]
'[clojure.spec.test.alpha :as stest]
'[clojure.spec.gen.alpha :as gen])
nil
「?さ」をspecで表現
	でキーワード	:user/length	に述語
number?	を登録
user> (s/def ::length number?)
:user/length
user> (doc ::length)
-------------------------
:user/length
Spec
number?
nil
s/def
「?さ」に?致する値を調べる
	で	::length	のspecに具体的な値が
?致するか確認
?致しなければ	::s/invalid
user> (s/conform ::length 3)
3
user> (s/conform ::length "3")
:clojure.spec.alpha/invalid
s/conform
?致しない原因を調べる
	で?致しない詳細原因を確認
ここでは
値	"3"	がspec	:user/length	の述語	number?
に不?致
user> (s/explain ::length "3")
val: "3" fails spec: :user/length predicate: number?
:clojure.spec.alpha/spec :user/length
:clojure.spec.alpha/value "3"
nil
s/explain
「?さ」のサンプルを?成
	で	 	互換なジェネレータを取得
	でサンプルを?成
user> (s/gen ::length)
#clojure.test.check.generators.Generator{:gen #function[clojure.
test.check.generators/such-that/fn--13745]}
user> (gen/sample (s/gen ::length))
(0.5 -1.0 -1 0.5 3.25 0 -3 0.6875 0.25 0)
s/gen test.check
gen/sample
「?さ」に制約を加える
論理演算?で制約を追加
	は論理積
cf.	
user> (s/def ::length (s/and number? pos?))
:user/length
user> (doc ::length)
-------------------------
:user/length
Spec
(and number? pos?)
nil
user> (gen/sample (s/gen ::length))
(0.5 3.0 0.5 1.375 1.6875 3.0 0.625 1.25 0.41015625 0.25)
s/and
s/or
「?さ」で辺a,	b,	cを表現
user> (s/def ::side-a ::length)
:user/side-a
user> (doc ::side-a)
-------------------------
:user/side-a
Spec
(and number? pos?)
nil
user> (s/def ::side-b ::length)
:user/side-b
user> (s/def ::side-c ::length)
:user/side-c
辺a,	b,	cを持つマップとして直?体
を表現
	で必須のキーを持つマップを表現
user> (s/def ::cuboid (s/keys :req [::side-a ::side-b ::side-c])
)
:user/cuboid
user> (doc ::cuboid)
-------------------------
:user/cuboid
Spec
(keys :req [:user/side-a :user/side-b :user/side-c])
nil
s/keys
直?体に?致する値を調べる
user> (s/conform ::cuboid #::{:side-a 1
:side-b 2
:side-c 3})
#:user{:side-a 1, :side-b 2, :side-c 3}
user> (s/conform ::cuboid #::{:side-a 1
:side-b "2"
:side-c 3})
:clojure.spec.alpha/invalid
?致しない原因を調べる
:user/side-b	の値	"2"	がspec	:user/length
の述語	number?	に不?致
マップのキーに対応するspecもチェックされる
user> (s/explain ::cuboid #::{:side-a 1
:side-b "2"
:side-c 3})
In: [:user/side-b] val: "2" fails spec: :user/length at: [:user/
side-b] predicate: number?
:clojure.spec.alpha/spec :user/cuboid
:clojure.spec.alpha/value #:user{:side-a 1, :side-b "2", :side-
c 3}
nil
値	#:user{:side-a 1, :side-d 2, :side-c
3}	がspec	:user/cuboid	の述語	(contains? %
:user/side-b)	に不?致
user> (s/explain ::cuboid #::{:side-a 1
:side-d 2
:side-c 3})
val: #:user{:side-a 1, :side-d 2, :side-c 3} fails spec: :user/c
uboid predicate: (contains? % :user/side-b)
:clojure.spec.alpha/spec :user/cuboid
:clojure.spec.alpha/value #:user{:side-a 1, :side-d 2, :side-c
3}
nil
値	#:user{:side-a 1, :side-c 3}	がspec
:user/cuboid	の述語	(contains? %
:user/side-b)	に不?致
user> (s/explain ::cuboid #::{:side-a 1
:side-c 3})
val: #:user{:side-a 1, :side-c 3} fails spec: :user/cuboid predi
cate: (contains? % :user/side-b)
:clojure.spec.alpha/spec :user/cuboid
:clojure.spec.alpha/value #:user{:side-a 1, :side-c 3}
nil
直?体のサンプルを?成
複合的なデータのサンプルも?成できる
user> (gen/sample (s/gen ::cuboid))
(#:user{:side-a 0.5, :side-b 1.0, :side-c 0.625} #:user{:side-a
0.5, :side-b 1.5, :side-c 2} #:user{:side-a 2.0, :side-b 4, :sid
e-c 1} #:user{:side-a 1.5, :side-b 1.0, :side-c 1} #:user{:side-
a 0.5, :side-b 12, :side-c 1.125} #:user{:side-a 49, :side-b 0.3
59375, :side-c 0.765625} #:user{:side-a 2, :side-b 1, :side-c 1.
25} #:user{:side-a 3.0, :side-b 0.5, :side-c 2.0} #:user{:side-a
1.3125, :side-b 1.0, :side-c 1.0} #:user{:side-a 5.265625, :sid
e-b 1.0625, :side-c 2.73828125})
直?体の体積計算の仕様を表現
	で関数	cuboid-volume	の引数と戻り値
に対するspecを登録
引数:	::cuboid	1要素のシーケンス
	は正規表現演算?
cf.	 ,	 ,	 ,	 ,	
戻り値:	数値
user> (s/fdef cuboid-volume
:args (s/cat :cuboid ::cuboid)
:ret number?)
user/cuboid-volume
s/fdef
s/cat
s/* s/+ s/? s/& s/alt
仕様を満たすように関数を実装
user> (defn cuboid-volume [{::keys [side-a side-b side-c]}]
(* side-a side-b side-c))
#'user/cuboid-volume
引数に対するチェックを有効化
stest/instrument
user> (doc cuboid-volume)
-------------------------
user/cuboid-volume
([#:user{:keys [side-a side-b side-c]}])
Spec
args: (cat :cuboid :user/cuboid)
ret: number?
nil
user> (stest/instrument)
[user/cuboid-volume]
引数のspecを満たす値に適?すると期待した計算
結果が得られる
user> (cuboid-volume #::{:side-a 1
:side-b 2
:side-c 3})
6
パス	[0 :user/side-b]	の値	"2"	がspec
:user/length	の述語	number?	に不?致	?	例外
user> (cuboid-volume #::{:side-a 1
:side-b "2"
:side-c 3})
ExceptionInfo Call to #'user/cuboid-volume did not conform to sp
ec:
In: [0 :user/side-b] val: "2" fails spec: :user/length at: [:arg
s :cuboid :user/side-b] predicate: number?
:clojure.spec.alpha/spec #object[clojure.spec.alpha$regex_spec_
impl$reify__1200 0x57e771b6 "clojure.spec.alpha$regex_spec_impl$
reify__1200@57e771b6"]
:clojure.spec.alpha/value (#:user{:side-a 1, :side-b "2", :side
-c 3})
:clojure.spec.alpha/args (#:user{:side-a 1, :side-b "2", :side-
c 3})
:clojure.spec.alpha/failure :instrument
:clojure.spec.test.alpha/caller {:file "form-init41134222269549
81451.clj", :line 188, :var-scope user/eval14130}
clojure.core/ex-info (core.clj:4744)
関数の動作確認
	で引数のspecを満たすランダム
な値で動作確認
結果はベクター	[引数 戻り値]	のシーケンス
user> (s/exercise-fn `cuboid-volume)
([(#:user{:side-a 2.0, :side-b 0.5, :side-c 0.5}) 0.5] [(#:user{
:side-a 0.75, :side-b 1.5, :side-c 0.75}) 0.84375] [(#:user{:sid
e-a 2.0, :side-b 1, :side-c 1.75}) 3.5] [(#:user{:side-a 4, :sid
e-b 4, :side-c 2}) 32] [(#:user{:side-a 2, :side-b 6, :side-c 1.
0}) 12.0] [(#:user{:side-a 1, :side-b 3, :side-c 6}) 18] [(#:use
r{:side-a 20, :side-b 1.0, :side-c 99}) 1980.0] [(#:user{:side-a
12, :side-b 890, :side-c 1.25}) 13350.0] [(#:user{:side-a 4, :s
ide-b 0.99609375, :side-c 2.0}) 7.96875] [(#:user{:side-a 3, :si
de-b 6.0, :side-c 9}) 162.0])
s/exercise-fn
?動プロパティベーストテスト
stest/check
user> (stest/check `cuboid-volume)
({:spec #object[clojure.spec.alpha$fspec_impl$reify__1215 0x765acd43 "c
:cause "integer overflow"
:via
[{:type java.lang.ArithmeticException
:message "integer overflow"
:at [clojure.lang.Numbers throwIntOverflow "Numbers.java" 1526]}]
:trace
[[clojure.lang.Numbers throwIntOverflow "Numbers.java" 1526]
[clojure.lang.Numbers multiply "Numbers.java" 1892]
[clojure.lang.Numbers$LongOps multiply "Numbers.java" 472]
[clojure.lang.Numbers multiply "Numbers.java" 148]
[user$cuboid_volume invokeStatic "form-init4113422226954981451.clj" 1
[user$cuboid_volume invoke "form-init4113422226954981451.clj" 155]
[clojure.lang.AFn applyToHelper "AFn.java" 154]
[clojure.lang.AFn applyTo "AFn.java" 144]
[clojure.core$apply invokeStatic "core.clj" 657]
[clojure.core$apply invoke "core.clj" 652]
[clojure.spec.test.alpha$check_call invokeStatic "alpha.clj" 292]
ここでは
乗算でinteger	overflowが発?しうることが判明
:smallest	[(#:user{:side-a	1,	:side-b
23021144,	:side-c	400647858198})]
user> (cuboid-volume #::{:side-a 1
:side-b 23021144
:side-c 400647858198})
ArithmeticException integer overflow clojure.lang.Numbers.throw
IntOverflow (Numbers.java:1526)
integer	overflowしないように関数	*	を	*'	に変更
user> (defn cuboid-volume [{::keys [side-a side-b side-c]}]
(*' side-a side-b side-c))
#'user/cuboid-volume
user> (cuboid-volume #::{:side-a 1
:side-b 23021144
:side-c 400647858198})
9223372036867738512N
デフォルト1000回の試?で正常にテストをパス
user> (stest/check `cuboid-volume)
({:spec #object[clojure.spec.alpha$fspec_impl$reify__1215 0x765a
cd43 "clojure.spec.alpha$fspec_impl$reify__1215@765acd43"], :clo
jure.spec.test.check/ret {:result true, :num-tests 1000, :seed 1
505803853835}, :sym user/cuboid-volume})
user> (stest/summarize-results *1)
{:sym user/cuboid-volume}
{:total 1, :check-passed 1}
最終結果
(ns spec-examples.geometry
(:require [clojure.spec.alpha :as s]))
;; specs
(s/def ::length (s/and number? pos?))
(s/def ::side-a ::length)
(s/def ::side-b ::length)
(s/def ::side-c ::length)
(s/def ::cuboid (s/keys :req [::side-a ::side-b ::side-c])
(s/fdef cuboid-volume
:args (s/cat :cuboid ::cuboid)
:ret number?)
;; implementation
(defn cuboid-volume [{::keys [side-a side-b side-c]}]
(*' side-a side-b side-c))
述語(predicate)で仕様が書ける
値に対する制約が柔軟に表現できる
Clojureの動的な性質と親和性が?常に?い
コンパイル時ではなく実?時
REPL駆動開発とプロパティベーストテストで制
約を満たしていることを保証する戦略
漸進的型付け/静的?語化とは異なる未来
?動プロパティベーストテストが便利
clojure.specを活?して
変更に強いClojureコードを書こう
(*> ? ?*)ゞ
Vive	les	S-expressions	!
Long	live	S-expressions!
Further	Reading
example	code
lagenorhynque/spec-examples
clojure.spec	vs	core.typed	vs	schema
of cial	site
clojure.spec	-	Rationale	and	Overview
spec	Guide
clojure/clojure	at	clojure-1.9.0-beta1
clojure/spec.alpha
clojure.spec	-	Clojure	v1.9	API
documentation
clojure/core.specs.alpha
clojure/core.typed
plumatic/schema
video
book
Spec-ulation	Keynote	-	Rich	Hickey
"Agility	&	Robustness:	Clojure	spec"	by	Stuart
Halloway
clojure.spec	-	David	Nolen
Clojure	spec	Screencast	Series
Programming	Clojure,	Third	Edition

More Related Content

What's hot (20)

罢飞颈迟迟别谤の蝉苍辞飞蹿濒补办别について
罢飞颈迟迟别谤の蝉苍辞飞蹿濒补办别について罢飞颈迟迟别谤の蝉苍辞飞蹿濒补办别について
罢飞颈迟迟别谤の蝉苍辞飞蹿濒补办别について
moai kids
?
SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021
Hiroshi Tokumaru
?
RLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for DjangoRLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for Django
Takayuki Shimizukawa
?
搁别诲颈蝉の特徴と活用方法について
搁别诲颈蝉の特徴と活用方法について搁别诲颈蝉の特徴と活用方法について
搁别诲颈蝉の特徴と活用方法について
Yuji Otani
?
骋辞の时刻に関するテスト
骋辞の时刻に関するテスト骋辞の时刻に関するテスト
骋辞の时刻に関するテスト
Kentaro Kawano
?
初心者向け惭辞苍驳辞顿叠のキホン!
初心者向け惭辞苍驳辞顿叠のキホン!初心者向け惭辞苍驳辞顿叠のキホン!
初心者向け惭辞苍驳辞顿叠のキホン!
Tetsutaro Watanabe
?
LINE LIVE のチャットが?30,000+/min のコメント投稿を捌くようになるまで
LINE LIVE のチャットが?30,000+/min のコメント投稿を捌くようになるまでLINE LIVE のチャットが?30,000+/min のコメント投稿を捌くようになるまで
LINE LIVE のチャットが?30,000+/min のコメント投稿を捌くようになるまで
LINE Corporation
?
ヤフー社内でやってる惭测厂蚕尝チューニングセミナー大公开
ヤフー社内でやってる惭测厂蚕尝チューニングセミナー大公开ヤフー社内でやってる惭测厂蚕尝チューニングセミナー大公开
ヤフー社内でやってる惭测厂蚕尝チューニングセミナー大公开
驰补丑辞辞!デベロッパーネットワーク
?
Coder sans peur du changement avec la meme pas mal hexagonal architecture
Coder sans peur du changement avec la meme pas mal hexagonal architectureCoder sans peur du changement avec la meme pas mal hexagonal architecture
Coder sans peur du changement avec la meme pas mal hexagonal architecture
Thomas Pierrain
?
0章 Linuxカーネルを読む前に最低限知っておくべきこと
0章 Linuxカーネルを読む前に最低限知っておくべきこと0章 Linuxカーネルを読む前に最低限知っておくべきこと
0章 Linuxカーネルを読む前に最低限知っておくべきこと
mao999
?
マイクロサービスバックエンド础笔滨のための搁贰厂罢と驳搁笔颁
マイクロサービスバックエンド础笔滨のための搁贰厂罢と驳搁笔颁マイクロサービスバックエンド础笔滨のための搁贰厂罢と驳搁笔颁
マイクロサービスバックエンド础笔滨のための搁贰厂罢と驳搁笔颁
disc99_
?
闯补惫补バイトコード入门
闯补惫补バイトコード入门闯补惫补バイトコード入门
闯补惫补バイトコード入门
Kota Mizushima
?
狈颈辫辫辞苍诲补苍箩颈氏に怒られても仕方ない、配列型と闯厂翱狈型の使い方
狈颈辫辫辞苍诲补苍箩颈氏に怒られても仕方ない、配列型と闯厂翱狈型の使い方狈颈辫辫辞苍诲补苍箩颈氏に怒られても仕方ない、配列型と闯厂翱狈型の使い方
狈颈辫辫辞苍诲补苍箩颈氏に怒られても仕方ない、配列型と闯厂翱狈型の使い方
kwatch
?
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方
Taku Miyakawa
?
最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5
最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5
最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5
Takahiro YAMADA
?
Workshop Spring  - Session 1 - L'offre Spring et les basesWorkshop Spring  - Session 1 - L'offre Spring et les bases
Workshop Spring - Session 1 - L'offre Spring et les bases
Antoine Rey
?
Embulk 20150411
Embulk 20150411Embulk 20150411
Embulk 20150411
Hiroshi Nakamura
?
マルチテナントのアプリケーション実装?実践编?
マルチテナントのアプリケーション実装?実践编?マルチテナントのアプリケーション実装?実践编?
マルチテナントのアプリケーション実装?実践编?
Yoshiki Nakagawa
?
さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)
Takanori Sejima
?
データ履歴管理のためのテンポラルデータモデルと搁别濒补诲辞尘辞の绍介 #jjug_ccc #ccc_g3
データ履歴管理のためのテンポラルデータモデルと搁别濒补诲辞尘辞の绍介 #jjug_ccc #ccc_g3 データ履歴管理のためのテンポラルデータモデルと搁别濒补诲辞尘辞の绍介 #jjug_ccc #ccc_g3
データ履歴管理のためのテンポラルデータモデルと搁别濒补诲辞尘辞の绍介 #jjug_ccc #ccc_g3
Hiroshi Ito
?
罢飞颈迟迟别谤の蝉苍辞飞蹿濒补办别について
罢飞颈迟迟别谤の蝉苍辞飞蹿濒补办别について罢飞颈迟迟别谤の蝉苍辞飞蹿濒补办别について
罢飞颈迟迟别谤の蝉苍辞飞蹿濒补办别について
moai kids
?
SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021
Hiroshi Tokumaru
?
RLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for DjangoRLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for Django
Takayuki Shimizukawa
?
搁别诲颈蝉の特徴と活用方法について
搁别诲颈蝉の特徴と活用方法について搁别诲颈蝉の特徴と活用方法について
搁别诲颈蝉の特徴と活用方法について
Yuji Otani
?
骋辞の时刻に関するテスト
骋辞の时刻に関するテスト骋辞の时刻に関するテスト
骋辞の时刻に関するテスト
Kentaro Kawano
?
初心者向け惭辞苍驳辞顿叠のキホン!
初心者向け惭辞苍驳辞顿叠のキホン!初心者向け惭辞苍驳辞顿叠のキホン!
初心者向け惭辞苍驳辞顿叠のキホン!
Tetsutaro Watanabe
?
LINE LIVE のチャットが?30,000+/min のコメント投稿を捌くようになるまで
LINE LIVE のチャットが?30,000+/min のコメント投稿を捌くようになるまでLINE LIVE のチャットが?30,000+/min のコメント投稿を捌くようになるまで
LINE LIVE のチャットが?30,000+/min のコメント投稿を捌くようになるまで
LINE Corporation
?
Coder sans peur du changement avec la meme pas mal hexagonal architecture
Coder sans peur du changement avec la meme pas mal hexagonal architectureCoder sans peur du changement avec la meme pas mal hexagonal architecture
Coder sans peur du changement avec la meme pas mal hexagonal architecture
Thomas Pierrain
?
0章 Linuxカーネルを読む前に最低限知っておくべきこと
0章 Linuxカーネルを読む前に最低限知っておくべきこと0章 Linuxカーネルを読む前に最低限知っておくべきこと
0章 Linuxカーネルを読む前に最低限知っておくべきこと
mao999
?
マイクロサービスバックエンド础笔滨のための搁贰厂罢と驳搁笔颁
マイクロサービスバックエンド础笔滨のための搁贰厂罢と驳搁笔颁マイクロサービスバックエンド础笔滨のための搁贰厂罢と驳搁笔颁
マイクロサービスバックエンド础笔滨のための搁贰厂罢と驳搁笔颁
disc99_
?
闯补惫补バイトコード入门
闯补惫补バイトコード入门闯补惫补バイトコード入门
闯补惫补バイトコード入门
Kota Mizushima
?
狈颈辫辫辞苍诲补苍箩颈氏に怒られても仕方ない、配列型と闯厂翱狈型の使い方
狈颈辫辫辞苍诲补苍箩颈氏に怒られても仕方ない、配列型と闯厂翱狈型の使い方狈颈辫辫辞苍诲补苍箩颈氏に怒られても仕方ない、配列型と闯厂翱狈型の使い方
狈颈辫辫辞苍诲补苍箩颈氏に怒られても仕方ない、配列型と闯厂翱狈型の使い方
kwatch
?
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方
Taku Miyakawa
?
最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5
最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5
最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5
Takahiro YAMADA
?
Workshop Spring  - Session 1 - L'offre Spring et les basesWorkshop Spring  - Session 1 - L'offre Spring et les bases
Workshop Spring - Session 1 - L'offre Spring et les bases
Antoine Rey
?
マルチテナントのアプリケーション実装?実践编?
マルチテナントのアプリケーション実装?実践编?マルチテナントのアプリケーション実装?実践编?
マルチテナントのアプリケーション実装?実践编?
Yoshiki Nakagawa
?
さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)
Takanori Sejima
?
データ履歴管理のためのテンポラルデータモデルと搁别濒补诲辞尘辞の绍介 #jjug_ccc #ccc_g3
データ履歴管理のためのテンポラルデータモデルと搁别濒补诲辞尘辞の绍介 #jjug_ccc #ccc_g3 データ履歴管理のためのテンポラルデータモデルと搁别濒补诲辞尘辞の绍介 #jjug_ccc #ccc_g3
データ履歴管理のためのテンポラルデータモデルと搁别濒补诲辞尘辞の绍介 #jjug_ccc #ccc_g3
Hiroshi Ito
?

Similar to Spectacular Future with clojure.spec (20)

TypeScript 1.0 オーバービュー
TypeScript 1.0 オーバービューTypeScript 1.0 オーバービュー
TypeScript 1.0 オーバービュー
Akira Inoue
?
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
Akira Inoue
?
Visual Studio 2012 Web 開発 ~ One ASP.NET から TypeScript まで ~
Visual Studio 2012 Web 開発 ~ One ASP.NET から TypeScript まで ~Visual Studio 2012 Web 開発 ~ One ASP.NET から TypeScript まで ~
Visual Studio 2012 Web 開発 ~ One ASP.NET から TypeScript まで ~
Akira Inoue
?
Okinawa.rb 第2回勉強会
Okinawa.rb 第2回勉強会Okinawa.rb 第2回勉強会
Okinawa.rb 第2回勉強会
Naoki Takaesu
?
Inside of excel 方眼紙撲滅委員会 #pyfes
Inside of excel 方眼紙撲滅委員会 #pyfesInside of excel 方眼紙撲滅委員会 #pyfes
Inside of excel 方眼紙撲滅委員会 #pyfes
Takeshi Komiya
?
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
Akira Inoue
?
var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18
var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18
var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18
Syo Ikeda
?
Pub/Sub model, msm, and asio
Pub/Sub model, msm, and asioPub/Sub model, msm, and asio
Pub/Sub model, msm, and asio
Takatoshi Kondo
?
More Better Nested Set
More Better Nested SetMore Better Nested Set
More Better Nested Set
xibbar
?
きつねさんでもわかるLlvm読書会 第2回
きつねさんでもわかるLlvm読書会 第2回きつねさんでもわかるLlvm読書会 第2回
きつねさんでもわかるLlvm読書会 第2回
Tomoya Kawanishi
?
第四回 JavaScriptから始めるプログラミング2016
第四回 JavaScriptから始めるプログラミング2016第四回 JavaScriptから始めるプログラミング2016
第四回 JavaScriptから始めるプログラミング2016
kyoto university
?
痴别谤颈濒补迟辞谤と厂测蝉迟别尘颁
痴别谤颈濒补迟辞谤と厂测蝉迟别尘颁痴别谤颈濒补迟辞谤と厂测蝉迟别尘颁
痴别谤颈濒补迟辞谤と厂测蝉迟别尘颁
Mr. Vengineer
?
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスするEWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
Kiyoshi Sawada
?
TypeScript と Visual Studio Code
TypeScript と Visual Studio CodeTypeScript と Visual Studio Code
TypeScript と Visual Studio Code
Akira Inoue
?
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みください
digitalghost
?
TypeScript 1.0 オーバービュー
TypeScript 1.0 オーバービューTypeScript 1.0 オーバービュー
TypeScript 1.0 オーバービュー
Akira Inoue
?
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
Akira Inoue
?
Visual Studio 2012 Web 開発 ~ One ASP.NET から TypeScript まで ~
Visual Studio 2012 Web 開発 ~ One ASP.NET から TypeScript まで ~Visual Studio 2012 Web 開発 ~ One ASP.NET から TypeScript まで ~
Visual Studio 2012 Web 開発 ~ One ASP.NET から TypeScript まで ~
Akira Inoue
?
Okinawa.rb 第2回勉強会
Okinawa.rb 第2回勉強会Okinawa.rb 第2回勉強会
Okinawa.rb 第2回勉強会
Naoki Takaesu
?
Inside of excel 方眼紙撲滅委員会 #pyfes
Inside of excel 方眼紙撲滅委員会 #pyfesInside of excel 方眼紙撲滅委員会 #pyfes
Inside of excel 方眼紙撲滅委員会 #pyfes
Takeshi Komiya
?
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
Akira Inoue
?
var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18
var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18
var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18
Syo Ikeda
?
Pub/Sub model, msm, and asio
Pub/Sub model, msm, and asioPub/Sub model, msm, and asio
Pub/Sub model, msm, and asio
Takatoshi Kondo
?
More Better Nested Set
More Better Nested SetMore Better Nested Set
More Better Nested Set
xibbar
?
きつねさんでもわかるLlvm読書会 第2回
きつねさんでもわかるLlvm読書会 第2回きつねさんでもわかるLlvm読書会 第2回
きつねさんでもわかるLlvm読書会 第2回
Tomoya Kawanishi
?
第四回 JavaScriptから始めるプログラミング2016
第四回 JavaScriptから始めるプログラミング2016第四回 JavaScriptから始めるプログラミング2016
第四回 JavaScriptから始めるプログラミング2016
kyoto university
?
痴别谤颈濒补迟辞谤と厂测蝉迟别尘颁
痴别谤颈濒补迟辞谤と厂测蝉迟别尘颁痴别谤颈濒补迟辞谤と厂测蝉迟别尘颁
痴别谤颈濒补迟辞谤と厂测蝉迟别尘颁
Mr. Vengineer
?
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスするEWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
Kiyoshi Sawada
?
TypeScript と Visual Studio Code
TypeScript と Visual Studio CodeTypeScript と Visual Studio Code
TypeScript と Visual Studio Code
Akira Inoue
?
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みください
digitalghost
?

More from Kent Ohashi (20)

From Scala/Clojure to Kotlin
From Scala/Clojure to KotlinFrom Scala/Clojure to Kotlin
From Scala/Clojure to Kotlin
Kent Ohashi
?
TDD with RDD: Clojure/LispのREPLで変わる開発体験
TDD with RDD: Clojure/LispのREPLで変わる開発体験TDD with RDD: Clojure/LispのREPLで変わる開発体験
TDD with RDD: Clojure/LispのREPLで変わる開発体験
Kent Ohashi
?
?の推し本紹介2024: 『脱?日本語なまり 英語(+α)実践音声学』
?の推し本紹介2024: 『脱?日本語なまり 英語(+α)実践音声学』?の推し本紹介2024: 『脱?日本語なまり 英語(+α)実践音声学』
?の推し本紹介2024: 『脱?日本語なまり 英語(+α)実践音声学』
Kent Ohashi
?
do Notation Equivalents in JVM languages: Scala, Kotlin, Clojure
do Notation Equivalents in JVM languages: Scala, Kotlin, Clojuredo Notation Equivalents in JVM languages: Scala, Kotlin, Clojure
do Notation Equivalents in JVM languages: Scala, Kotlin, Clojure
Kent Ohashi
?
Exploring Collections in JVM Languages through Internals of map Function
Exploring Collections in JVM Languages through Internals of map FunctionExploring Collections in JVM Languages through Internals of map Function
Exploring Collections in JVM Languages through Internals of map Function
Kent Ohashi
?
Kotlin Meets Data-Oriented Programming: Kotlinで実践する「データ指向プログラミング」
Kotlin Meets Data-Oriented Programming: Kotlinで実践する「データ指向プログラミング」Kotlin Meets Data-Oriented Programming: Kotlinで実践する「データ指向プログラミング」
Kotlin Meets Data-Oriented Programming: Kotlinで実践する「データ指向プログラミング」
Kent Ohashi
?
搁顿叠でのツリー表现入门2024
搁顿叠でのツリー表现入门2024搁顿叠でのツリー表现入门2024
搁顿叠でのツリー表现入门2024
Kent Ohashi
?
ミュータビリティとイミュータビリティの狭間: 関数型言語使いから見たKotlinコレクション
ミュータビリティとイミュータビリティの狭間: 関数型言語使いから見たKotlinコレクションミュータビリティとイミュータビリティの狭間: 関数型言語使いから見たKotlinコレクション
ミュータビリティとイミュータビリティの狭間: 関数型言語使いから見たKotlinコレクション
Kent Ohashi
?
インターフェース定義言語から学ぶモダンなWeb API方式: REST, GraphQL, gRPC
インターフェース定義言語から学ぶモダンなWeb API方式: REST, GraphQL, gRPCインターフェース定義言語から学ぶモダンなWeb API方式: REST, GraphQL, gRPC
インターフェース定義言語から学ぶモダンなWeb API方式: REST, GraphQL, gRPC
Kent Ohashi
?
Team Geek Revisited
Team Geek RevisitedTeam Geek Revisited
Team Geek Revisited
Kent Ohashi
?
Scala vs Clojure?: The Rise and Fall of Functional Languages in Opt Technologies
Scala vs Clojure?: The Rise and Fall of Functional Languages in Opt TechnologiesScala vs Clojure?: The Rise and Fall of Functional Languages in Opt Technologies
Scala vs Clojure?: The Rise and Fall of Functional Languages in Opt Technologies
Kent Ohashi
?
颁濒辞箩耻谤别コレクションで探る颈尘尘耻迟补产濒别で辫别谤蝉颈蝉迟别苍迟な世界
颁濒辞箩耻谤别コレクションで探る颈尘尘耻迟补产濒别で辫别谤蝉颈蝉迟别苍迟な世界颁濒辞箩耻谤别コレクションで探る颈尘尘耻迟补产濒别で辫别谤蝉颈蝉迟别苍迟な世界
颁濒辞箩耻谤别コレクションで探る颈尘尘耻迟补产濒别で辫别谤蝉颈蝉迟别苍迟な世界
Kent Ohashi
?
英語学習者のためのフランス語文法入門: フランス語完全理解(?)
英語学習者のためのフランス語文法入門: フランス語完全理解(?)英語学習者のためのフランス語文法入門: フランス語完全理解(?)
英語学習者のためのフランス語文法入門: フランス語完全理解(?)
Kent Ohashi
?
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミングJavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
Kent Ohashi
?
実用のための语源学入门
実用のための语源学入门実用のための语源学入门
実用のための语源学入门
Kent Ohashi
?
メタプログラミング入门
メタプログラミング入门メタプログラミング入门
メタプログラミング入门
Kent Ohashi
?
労働法の世界
労働法の世界労働法の世界
労働法の世界
Kent Ohashi
?
颁濒辞箩耻谤别で作る&辩耻辞迟;蝉颈尘辫濒别&辩耻辞迟;な顿厂尝
颁濒辞箩耻谤别で作る&辩耻辞迟;蝉颈尘辫濒别&辩耻辞迟;な顿厂尝颁濒辞箩耻谤别で作る&辩耻辞迟;蝉颈尘辫濒别&辩耻辞迟;な顿厂尝
颁濒辞箩耻谤别で作る&辩耻辞迟;蝉颈尘辫濒别&辩耻辞迟;な顿厂尝
Kent Ohashi
?
骋谤补辫丑蚕尝入门
骋谤补辫丑蚕尝入门骋谤补辫丑蚕尝入门
骋谤补辫丑蚕尝入门
Kent Ohashi
?
たのしい多言语学习
たのしい多言语学习たのしい多言语学习
たのしい多言语学习
Kent Ohashi
?
From Scala/Clojure to Kotlin
From Scala/Clojure to KotlinFrom Scala/Clojure to Kotlin
From Scala/Clojure to Kotlin
Kent Ohashi
?
TDD with RDD: Clojure/LispのREPLで変わる開発体験
TDD with RDD: Clojure/LispのREPLで変わる開発体験TDD with RDD: Clojure/LispのREPLで変わる開発体験
TDD with RDD: Clojure/LispのREPLで変わる開発体験
Kent Ohashi
?
?の推し本紹介2024: 『脱?日本語なまり 英語(+α)実践音声学』
?の推し本紹介2024: 『脱?日本語なまり 英語(+α)実践音声学』?の推し本紹介2024: 『脱?日本語なまり 英語(+α)実践音声学』
?の推し本紹介2024: 『脱?日本語なまり 英語(+α)実践音声学』
Kent Ohashi
?
do Notation Equivalents in JVM languages: Scala, Kotlin, Clojure
do Notation Equivalents in JVM languages: Scala, Kotlin, Clojuredo Notation Equivalents in JVM languages: Scala, Kotlin, Clojure
do Notation Equivalents in JVM languages: Scala, Kotlin, Clojure
Kent Ohashi
?
Exploring Collections in JVM Languages through Internals of map Function
Exploring Collections in JVM Languages through Internals of map FunctionExploring Collections in JVM Languages through Internals of map Function
Exploring Collections in JVM Languages through Internals of map Function
Kent Ohashi
?
Kotlin Meets Data-Oriented Programming: Kotlinで実践する「データ指向プログラミング」
Kotlin Meets Data-Oriented Programming: Kotlinで実践する「データ指向プログラミング」Kotlin Meets Data-Oriented Programming: Kotlinで実践する「データ指向プログラミング」
Kotlin Meets Data-Oriented Programming: Kotlinで実践する「データ指向プログラミング」
Kent Ohashi
?
搁顿叠でのツリー表现入门2024
搁顿叠でのツリー表现入门2024搁顿叠でのツリー表现入门2024
搁顿叠でのツリー表现入门2024
Kent Ohashi
?
ミュータビリティとイミュータビリティの狭間: 関数型言語使いから見たKotlinコレクション
ミュータビリティとイミュータビリティの狭間: 関数型言語使いから見たKotlinコレクションミュータビリティとイミュータビリティの狭間: 関数型言語使いから見たKotlinコレクション
ミュータビリティとイミュータビリティの狭間: 関数型言語使いから見たKotlinコレクション
Kent Ohashi
?
インターフェース定義言語から学ぶモダンなWeb API方式: REST, GraphQL, gRPC
インターフェース定義言語から学ぶモダンなWeb API方式: REST, GraphQL, gRPCインターフェース定義言語から学ぶモダンなWeb API方式: REST, GraphQL, gRPC
インターフェース定義言語から学ぶモダンなWeb API方式: REST, GraphQL, gRPC
Kent Ohashi
?
Team Geek Revisited
Team Geek RevisitedTeam Geek Revisited
Team Geek Revisited
Kent Ohashi
?
Scala vs Clojure?: The Rise and Fall of Functional Languages in Opt Technologies
Scala vs Clojure?: The Rise and Fall of Functional Languages in Opt TechnologiesScala vs Clojure?: The Rise and Fall of Functional Languages in Opt Technologies
Scala vs Clojure?: The Rise and Fall of Functional Languages in Opt Technologies
Kent Ohashi
?
颁濒辞箩耻谤别コレクションで探る颈尘尘耻迟补产濒别で辫别谤蝉颈蝉迟别苍迟な世界
颁濒辞箩耻谤别コレクションで探る颈尘尘耻迟补产濒别で辫别谤蝉颈蝉迟别苍迟な世界颁濒辞箩耻谤别コレクションで探る颈尘尘耻迟补产濒别で辫别谤蝉颈蝉迟别苍迟な世界
颁濒辞箩耻谤别コレクションで探る颈尘尘耻迟补产濒别で辫别谤蝉颈蝉迟别苍迟な世界
Kent Ohashi
?
英語学習者のためのフランス語文法入門: フランス語完全理解(?)
英語学習者のためのフランス語文法入門: フランス語完全理解(?)英語学習者のためのフランス語文法入門: フランス語完全理解(?)
英語学習者のためのフランス語文法入門: フランス語完全理解(?)
Kent Ohashi
?
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミングJavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
Kent Ohashi
?
実用のための语源学入门
実用のための语源学入门実用のための语源学入门
実用のための语源学入门
Kent Ohashi
?
メタプログラミング入门
メタプログラミング入门メタプログラミング入门
メタプログラミング入门
Kent Ohashi
?
颁濒辞箩耻谤别で作る&辩耻辞迟;蝉颈尘辫濒别&辩耻辞迟;な顿厂尝
颁濒辞箩耻谤别で作る&辩耻辞迟;蝉颈尘辫濒别&辩耻辞迟;な顿厂尝颁濒辞箩耻谤别で作る&辩耻辞迟;蝉颈尘辫濒别&辩耻辞迟;な顿厂尝
颁濒辞箩耻谤别で作る&辩耻辞迟;蝉颈尘辫濒别&辩耻辞迟;な顿厂尝
Kent Ohashi
?
骋谤补辫丑蚕尝入门
骋谤补辫丑蚕尝入门骋谤补辫丑蚕尝入门
骋谤补辫丑蚕尝入门
Kent Ohashi
?
たのしい多言语学习
たのしい多言语学习たのしい多言语学习
たのしい多言语学习
Kent Ohashi
?

Spectacular Future with clojure.spec