SlideShare a Scribd company logo
#kbkz_tech




class HogeOperation {
private(set) var isPrepared = false
func prepare() {
guard !isPrepared else {
fatalError("prepare を複数回呼ばないこと")
}
isPrepared = true
}
}
// Init 状態の HogeOperation を生成
let operation = HogeOperation<Init>()
// 最初は prepared を呼べて準備完了したものを取得可能
let preparedOp = operation.prepared()
// 準備が終われば prepared はビルドエラーで実行不可
preparedOp.prepared()
// これで "操作状態を表現する型" を表現
protocol OperationState {}
// 操作状態ごとにクラスを定義
class Init: OperationState {}
class Prepared: OperationState {}
// 型パラメーターで型に状態を付与
class HogeOperation<State: OperationState> {
/*
今回は内部で、
型パラメーターを使わないのがポイント
*/
}
extension HogeOperation where State: Init {
// 準備を実行し、準備完了状態のインスタンスを返す
func prepared() -> HogeOperation<Prepared> {…}
}
extension HogeOperation where State: Prepared {
// 目的の操作を実行する
func execute() {…}
}
let operation = HogeOperation<Init>()
// Init 状態では、まだ execute は存在しない
operation.execute()
// prepared を呼ぶことで Prepared 状態のものを取得
let preparedOp = operation.prepared()
// Prepared 状態には、もう prepared は存在しない
preparedOp.prepared()
let operation = HogeOperation<Init>()
// HogeOperation<Init> 型だから prepared が呼べる
let preparedOp: HogeOperation<Prepared>()
= operation.prepared()
// HogeOperation<Prepared> 型だから execute が呼べる
preparedOp.execute()
// Init クラスや Prepared クラスを、実行時には使わない
// ビルドの段階で、もう役目が済んでいる
let operation = HogeOperation<Init>()
let preparedOp = operation.prepared()
let type1 = type(of: operation)
let type2 = type(of: preparedOp)
type1 == type2 // false
// 型パラメーターで型に状態を付与
class HogeOperation<State: OperationState> {
/*
内部では、型パラメーターを使っていない
型の在り方を説明するためだけに使っている
*/
/// Phantom Type に出逢う前の認識
// Array はテンプレート的なもので…
struct Array<Element> {
}
// 型パラメーターによって、異なる型になる
let values: Array<Int> = Array<String>()
// protocol OperationState {}
// class Init: OperationState {}
// class Prepared: OperationState {}
class Operation {
fileprivate var data: OperationData
fileprivate init(data: OperationData) {
self.data = data
}
func mob() {}
}
class OperationInit: Operation {
convenience init() {…}
func prepared() -> OperationPrepared {…}
}
class OperationPrepared: Operation {
func execute() {…}
}
let operation = OperationInit()
let preparedOp = operation.prepared()
preparedOp.execute()
struct OperationInit {
fileprivate var data: OperationData
fileprivate init(data: OperationData) {…}
// 共通機能
func mob() {}
// 固有の機能
init() {…}
func prepared() -> OperationPrepared {…}
}
struct OperationPrepared {
fileprivate var data: OperationData
fileprivate init(data: OperationData) {…}
// 共通機能
func mob() {}
// 固有の機能
func execute() {…}
}
let operation = OperationInit()
let preparedOp = operation.prepared()
preparedOp.execute()
protocol Operation {}
struct OperationInit: Operation {
…
}
struct OperationPrepared: Operation {
…
}
struct Operation {
struct Init {
…
}
struct Prepared {
…
}
}
let operation = Operation.Init()
let preparedOp = operation.prepared()
preparedOp.execute()
class Operation {
fileprivate var data: OperationData
fileprivate init(data: OperationData) {
self.data = data
}
func mob() {}
}
extension Operation {
class Init: Operation {
…
}
class Prepared: Operation {
…
}
}
let operation = Operation.Init()
let preparedOp = operation.prepared()
preparedOp.execute()
class HogeOperation<State: OperationState> {
func mob() {…}
}
extension HogeOperation where State: Init {
func prepared() -> HogeOperation<Prepared> {…}
}
extension HogeOperation where State: Prepared {
func execute() {…}
}
let operation = HogeOperation<Init>()
operation.execute()
let operation = OperationInit()
operation.execute()
// 準備前と準備後を、自分自身や同じ変数に書き戻せない
var operation = HogeOperation<Init>()
operation = operation.prepared()
protocol Operation {}
class HogeOperation<State: OperationState>: Operation {
}
var op: Operation
op = HogeOperation<Init>()
op = (op as! HogeOperation<Init>).prepared()
op = (op as! HogeOperation<Prepared>).execute()
class Driver {
init(channel: Int? = nil, volume: Int? = nil,
pan: Int? = nil, format: Format? = nil,
route: Route? = nil) {
}
}
// 設定項目に何があるかや、設定順番に気を使う
let driver = Driver(volume: 10,
format: ulaw, route: .speaker)
// 本体のクラスを Phantom Type で定義して…
class Driver<State> where State: AudioState {
}
// 準備が整ったときの機能を実装し…
extension Driver where State: Ready {
func start() { … }
}
// 初期化中にできることを規定すると…
extension Driver where State: Setup {
func prepared() -> Driver<Ready> { … }
func set(channel: Int) -> Driver { return self }
func set(volume: Int) -> Driver { return self }
func set(pan: Int) -> Driver { return self }
func set(format: Format) -> Driver { return self }
func set(route: Route) -> Driver { return self }
}
// 初期設定では、順番を気にせず設定できる・補完が効く
let driver = Driver<Setup>()
.set(format: ulaw)
.set(volume: 10)
.set(route: .speaker)
.prepared() // ここで Driver<Ready>() を返す
// 設定完了を宣言 (prepared) して、使い始める
driver.start()
let driver = Driver<Setup>()
.format // → Driver<FormatSetup>
.set(sampleRate: 44100)
.set(channelsPerFrame: 2)
.general // → Driver<GeneralSetup>
.set(volume: 10)
.set(route: .speaker)
.prepared() // → Driver<Ready>
let driver = Driver.setup() // → DriverSetup
.format // → FormatSetup
.set(sampleRate: 44100)
.set(channelsPerFrame: 2)
.general // → AudioSetup
.set(volume: 10)
.set(route: .speaker)
.prepared() // → Driver
// 設定項目を、初期値を持った構造体で用意して…
struct Description {
var channel: Int = default
var volume: Int = default
var pan: Int = default
var format: Format = default
var route: Route = default
}
let description = Description()
description.format.sampleRate = 44100
description.format.channelsPerFrame = 2
description.volume = 10
description.route = .speaker
// Driver は Description で初期化するようにして…
class Driver {
init(description: Description) { … }
}
// 設定項目を渡して、初期化を完成する
let driver = Driver(description: description)
class Controller {
var environment: Environment<Neutral>
}
struct Environment<State> {
fileprivate(set) var platform: Platform
fileprivate(set) var version: Double
func startEditing() -> Environment<Editing> {
return Environment<Editing>(
platform: platform, version: version)
}
}
extension Environment where State: Editing {
mutating func set(platform: Platform) { … }
mutating func set(version: Double) { … }
func endEditing() -> Environment<Neutral> {
return Environment<Neutral>(
platform: platform, version: version)
}
}
func update() {
// 編集状態で取り出さないと、書き込めない
var environment = self.environment.startEditing()
environment.set(platform: .macOS)
environment.set(version: Platform.macOS.latest)
// ローカルで編集を終了したら、書き戻す
self.environment = environment.endEditing()
}
extension Environment where State: Editing {
var platform: Platform
var version: Double
// 同じ内容の、別インスタンスを作り直している
func endEditing() -> Environment<Neutral> {
return Environment<Neutral>(
platform: platform, version: version)
}
extension Environment where State: Editing {
// 内容を原始的にコピーしないといけないとき
func endEditing() -> Environment<Neutral> {
var result = Environment<Neutral>()
result.platform = platform
result.version = version
return result
}
struct Environment<State> {
fileprivate(set) var platform: Platform
fileprivate(set) var version: Double
}
extension Environment {
fileprivate init<S>(takeover: Environment<S>) {
platform = takeover.platform
version = takeover.version
}
}
extension Environment where State: Editing {
func endEditing() -> Environment<Neutral> {
return Environment<Neutral>(takeover: self)
}
}
struct Environment<State> {
// データをここで集中管理する
fileprivate struct Context {
var platform: Platform
var version: Double
}
// これだけを引き継げば済む状況を作る
fileprivate var _context: Context
}
extension Environment {
fileprivate init(context: Context) {
_context = context
}
}
extension Environment where State: Editing {
func endEditing() -> Environment<Neutral> {
return Environment<Neutral>(context: _context)
}
}
extension Environment {
var platform: Platform {
get { _context.platform }
set { _context.platform = newValue }
}
var version: Double {
get { _context.version }
set { _context.version = newValue }
}
extension Environment where State: Editing {
func endEditing() -> Environment<Neutral> {
// 準備不要で、いきなりビットキャスト可能
return unsafeBitCast(self,
to: Environment<Neutral>.self)
}
}
extension Environment {
fileprivate init<S>(takeover: Environment<S>) {
self = unsafeBitCast(takeover,
to: Environment.self)
}
}
let sub: Base = Sub()
let base: Base = Base()
// 実体が Sub なので、全ての機能が使える
let obj: Sub = unsafeBitCast(sub, to: Sub.self)
// 実体が Base なので、Sub の機能を使うとクラッシュする
let obj: Sub = unsafeBitCast(base, to: Sub.self)
class Test: OperationState {}
extension HogeOperation where State: Test {
func testSomething() {…}
}
extension HogeOperation where State: Init {
func testing() -> HogeOperation<Test> {…}
}
// Test 状態を Prepared から継承させれば…
class Test: Prepared {}
// Test には Prepared の機能も備わる
extension HogeOperation where State: Prepared {
func execute() {…}
}
extension HogeOperation where State: Test {
func testSomething() {…}
}
はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech
はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech
はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech
はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech

More Related Content

What's hot

Debugging: Rules & Tools
Debugging: Rules & ToolsDebugging: Rules & Tools
Debugging: Rules & Tools
Ian Barber
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
Hisateru Tanaka
 
Django
Django Django
Django
Toru Furukawa
 
Building apache modules
Building apache modulesBuilding apache modules
Building apache modules
Marian Marinov
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
Bastian Feder
 
Utility Modules That You Should Know About
Utility Modules That You Should Know AboutUtility Modules That You Should Know About
Utility Modules That You Should Know About
joshua.mcadams
 
Function Call Optimization
Function Call OptimizationFunction Call Optimization
Function Call Optimization
ppd1961
 
How to ride a whale
How to ride a whaleHow to ride a whale
How to ride a whale
Vincent Vermersh
 
Workshop unittesting
Workshop unittestingWorkshop unittesting
Workshop unittesting
Joshua Thijssen
 
Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015
Lin Yo-An
 
Optimizing mysql stored routines uc2010
Optimizing mysql stored routines uc2010Optimizing mysql stored routines uc2010
Optimizing mysql stored routines uc2010Roland Bouman
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
mfrost503
 
Writing MySQL User-defined Functions in JavaScript
Writing MySQL User-defined Functions in JavaScriptWriting MySQL User-defined Functions in JavaScript
Writing MySQL User-defined Functions in JavaScriptRoland Bouman
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
Jace Ju
 
3. writing MySql plugins for the information schema
3. writing MySql plugins for the information schema3. writing MySql plugins for the information schema
3. writing MySql plugins for the information schemaRoland Bouman
 
High Performance tDiary
High Performance tDiaryHigh Performance tDiary
High Performance tDiary
Hiroshi SHIBATA
 
Devinsampa nginx-scripting
Devinsampa nginx-scriptingDevinsampa nginx-scripting
Devinsampa nginx-scriptingTony Fabeen
 
Perl Sucks - and what to do about it
Perl Sucks - and what to do about itPerl Sucks - and what to do about it
Perl Sucks - and what to do about it
2shortplanks
 
Using ngx_lua in UPYUN 2
Using ngx_lua in UPYUN 2Using ngx_lua in UPYUN 2
Using ngx_lua in UPYUN 2
Cong Zhang
 

What's hot (20)

Debugging: Rules & Tools
Debugging: Rules & ToolsDebugging: Rules & Tools
Debugging: Rules & Tools
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
Django
Django Django
Django
 
Building apache modules
Building apache modulesBuilding apache modules
Building apache modules
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
 
Utility Modules That You Should Know About
Utility Modules That You Should Know AboutUtility Modules That You Should Know About
Utility Modules That You Should Know About
 
Function Call Optimization
Function Call OptimizationFunction Call Optimization
Function Call Optimization
 
How to ride a whale
How to ride a whaleHow to ride a whale
How to ride a whale
 
Workshop unittesting
Workshop unittestingWorkshop unittesting
Workshop unittesting
 
Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015
 
Gun make
Gun makeGun make
Gun make
 
Optimizing mysql stored routines uc2010
Optimizing mysql stored routines uc2010Optimizing mysql stored routines uc2010
Optimizing mysql stored routines uc2010
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
 
Writing MySQL User-defined Functions in JavaScript
Writing MySQL User-defined Functions in JavaScriptWriting MySQL User-defined Functions in JavaScript
Writing MySQL User-defined Functions in JavaScript
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
3. writing MySql plugins for the information schema
3. writing MySql plugins for the information schema3. writing MySql plugins for the information schema
3. writing MySql plugins for the information schema
 
High Performance tDiary
High Performance tDiaryHigh Performance tDiary
High Performance tDiary
 
Devinsampa nginx-scripting
Devinsampa nginx-scriptingDevinsampa nginx-scripting
Devinsampa nginx-scripting
 
Perl Sucks - and what to do about it
Perl Sucks - and what to do about itPerl Sucks - and what to do about it
Perl Sucks - and what to do about it
 
Using ngx_lua in UPYUN 2
Using ngx_lua in UPYUN 2Using ngx_lua in UPYUN 2
Using ngx_lua in UPYUN 2
 

Viewers also liked

Minimal Cake Pattern in Swift
Minimal Cake Pattern in SwiftMinimal Cake Pattern in Swift
Minimal Cake Pattern in Swift
Hikaru Yoshimura
 
Androidオールスターズ2016 yanzm
Androidオールスターズ2016 yanzmAndroidオールスターズ2016 yanzm
Androidオールスターズ2016 yanzm
Yuki Anzai
 
なるべくコードを書かないAndroid開発
なるべくコードを書かないAndroid開発なるべくコードを書かないAndroid開発
なるべくコードを書かないAndroid開発
Hiroshi Kikuchi
 
はじめようlocalization
はじめようlocalizationはじめようlocalization
はじめようlocalization
João Orui
 
Phantom Type in Scala
Phantom Type in ScalaPhantom Type in Scala
Phantom Type in Scala
Yasuyuki Maeda
 
Advance text rendering in i os
Advance text rendering in i osAdvance text rendering in i os
Advance text rendering in i osConfiz
 
Hi performance table views with QuartzCore and CoreText
Hi performance table views with QuartzCore and CoreTextHi performance table views with QuartzCore and CoreText
Hi performance table views with QuartzCore and CoreText
Mugunth Kumar
 
日本の祝祭日を計算してカレンダ-に表示するアプリサンプル
日本の祝祭日を計算してカレンダ-に表示するアプリサンプル日本の祝祭日を計算してカレンダ-に表示するアプリサンプル
日本の祝祭日を計算してカレンダ-に表示するアプリサンプル
Fumiya Sakai
 
What's New in User Notifications Framework - WWDC16. Meetup @Wantedly with 日本...
What's New in User Notifications Framework - WWDC16. Meetup @Wantedly with 日本...What's New in User Notifications Framework - WWDC16. Meetup @Wantedly with 日本...
What's New in User Notifications Framework - WWDC16. Meetup @Wantedly with 日本...
将之 小野
 
リテラルと型の続きの話 #__swift__
リテラルと型の続きの話 #__swift__リテラルと型の続きの話 #__swift__
リテラルと型の続きの話 #__swift__
Tomohiro Kumagai
 
Swift + GraphQL
Swift + GraphQLSwift + GraphQL
Swift + GraphQL
Sommer Panage
 
バ、バカな...!ハッカソンの中で成長しているだと...!?
バ、バカな...!ハッカソンの中で成長しているだと...!?バ、バカな...!ハッカソンの中で成長しているだと...!?
バ、バカな...!ハッカソンの中で成長しているだと...!?
Kenji Tanaka
 
多人数iOSアプリ開発を考える
多人数iOSアプリ開発を考える多人数iOSアプリ開発を考える
多人数iOSアプリ開発を考える
sasaron 397
 
Web エンジニアが postgre sql を選ぶ 3 つの理由
Web エンジニアが postgre sql を選ぶ 3 つの理由Web エンジニアが postgre sql を選ぶ 3 つの理由
Web エンジニアが postgre sql を選ぶ 3 つの理由
Soudai Sone
 
RxSwift x Realm
RxSwift x RealmRxSwift x Realm
RxSwift x Realm
Kosuke Usami
 
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorpSwift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Tomohiro Kumagai
 
アメブロの大規模システム刷新と それを支えるSpring
アメブロの大規模システム刷新と それを支えるSpringアメブロの大規模システム刷新と それを支えるSpring
アメブロの大規模システム刷新と それを支えるSpring
Takuya Hattori
 
20170302 tryswift tasting_tests
20170302 tryswift tasting_tests20170302 tryswift tasting_tests
20170302 tryswift tasting_tests
Kazuaki Matsuo
 
Type-safe Web APIs with Protocol Buffers in Swift at iOSCon
Type-safe Web APIs with Protocol Buffers in Swift at iOSConType-safe Web APIs with Protocol Buffers in Swift at iOSCon
Type-safe Web APIs with Protocol Buffers in Swift at iOSCon
Yusuke Kita
 
Vue.js with Go
Vue.js with GoVue.js with Go
Vue.js with Go
Kazuhiro Kubota
 

Viewers also liked (20)

Minimal Cake Pattern in Swift
Minimal Cake Pattern in SwiftMinimal Cake Pattern in Swift
Minimal Cake Pattern in Swift
 
Androidオールスターズ2016 yanzm
Androidオールスターズ2016 yanzmAndroidオールスターズ2016 yanzm
Androidオールスターズ2016 yanzm
 
なるべくコードを書かないAndroid開発
なるべくコードを書かないAndroid開発なるべくコードを書かないAndroid開発
なるべくコードを書かないAndroid開発
 
はじめようlocalization
はじめようlocalizationはじめようlocalization
はじめようlocalization
 
Phantom Type in Scala
Phantom Type in ScalaPhantom Type in Scala
Phantom Type in Scala
 
Advance text rendering in i os
Advance text rendering in i osAdvance text rendering in i os
Advance text rendering in i os
 
Hi performance table views with QuartzCore and CoreText
Hi performance table views with QuartzCore and CoreTextHi performance table views with QuartzCore and CoreText
Hi performance table views with QuartzCore and CoreText
 
日本の祝祭日を計算してカレンダ-に表示するアプリサンプル
日本の祝祭日を計算してカレンダ-に表示するアプリサンプル日本の祝祭日を計算してカレンダ-に表示するアプリサンプル
日本の祝祭日を計算してカレンダ-に表示するアプリサンプル
 
What's New in User Notifications Framework - WWDC16. Meetup @Wantedly with 日本...
What's New in User Notifications Framework - WWDC16. Meetup @Wantedly with 日本...What's New in User Notifications Framework - WWDC16. Meetup @Wantedly with 日本...
What's New in User Notifications Framework - WWDC16. Meetup @Wantedly with 日本...
 
リテラルと型の続きの話 #__swift__
リテラルと型の続きの話 #__swift__リテラルと型の続きの話 #__swift__
リテラルと型の続きの話 #__swift__
 
Swift + GraphQL
Swift + GraphQLSwift + GraphQL
Swift + GraphQL
 
バ、バカな...!ハッカソンの中で成長しているだと...!?
バ、バカな...!ハッカソンの中で成長しているだと...!?バ、バカな...!ハッカソンの中で成長しているだと...!?
バ、バカな...!ハッカソンの中で成長しているだと...!?
 
多人数iOSアプリ開発を考える
多人数iOSアプリ開発を考える多人数iOSアプリ開発を考える
多人数iOSアプリ開発を考える
 
Web エンジニアが postgre sql を選ぶ 3 つの理由
Web エンジニアが postgre sql を選ぶ 3 つの理由Web エンジニアが postgre sql を選ぶ 3 つの理由
Web エンジニアが postgre sql を選ぶ 3 つの理由
 
RxSwift x Realm
RxSwift x RealmRxSwift x Realm
RxSwift x Realm
 
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorpSwift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
 
アメブロの大規模システム刷新と それを支えるSpring
アメブロの大規模システム刷新と それを支えるSpringアメブロの大規模システム刷新と それを支えるSpring
アメブロの大規模システム刷新と それを支えるSpring
 
20170302 tryswift tasting_tests
20170302 tryswift tasting_tests20170302 tryswift tasting_tests
20170302 tryswift tasting_tests
 
Type-safe Web APIs with Protocol Buffers in Swift at iOSCon
Type-safe Web APIs with Protocol Buffers in Swift at iOSConType-safe Web APIs with Protocol Buffers in Swift at iOSCon
Type-safe Web APIs with Protocol Buffers in Swift at iOSCon
 
Vue.js with Go
Vue.js with GoVue.js with Go
Vue.js with Go
 

Similar to はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech

Centos config
Centos configCentos config
Centos config
Muhammad Abdi
 
If love is_blind_-_tiffany
If love is_blind_-_tiffanyIf love is_blind_-_tiffany
If love is_blind_-_tiffanytenka
 
Crushing React bugs with Jest and Enzyme
Crushing React bugs with Jest and EnzymeCrushing React bugs with Jest and Enzyme
Crushing React bugs with Jest and Enzyme
All Things Open
 
Exercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera CymbronExercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera Cymbroncymbron
 
Advance Java Programs skeleton
Advance Java Programs skeletonAdvance Java Programs skeleton
Advance Java Programs skeleton
Iram Ramrajkar
 
Node.js basics
Node.js basicsNode.js basics
Node.js basicsBen Lin
 
NodeJs
NodeJsNodeJs
NodeJs
dizabl
 
Spring data iii
Spring data iiiSpring data iii
Spring data iii
명철 강
 
こわくないよ❤️ Playframeworkソースコードリーディング入門
こわくないよ❤️ Playframeworkソースコードリーディング入門こわくないよ❤️ Playframeworkソースコードリーディング入門
こわくないよ❤️ Playframeworkソースコードリーディング入門
tanacasino
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
Visual Engineering
 
Txjs
TxjsTxjs
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
Lars Jankowfsky
 
Hadoop
HadoopHadoop
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
Thierry Wasylczenko
 
Puppet Camp LA 2015: Basic Puppet Module Design (Beginner)
Puppet Camp LA  2015: Basic Puppet Module Design (Beginner)Puppet Camp LA  2015: Basic Puppet Module Design (Beginner)
Puppet Camp LA 2015: Basic Puppet Module Design (Beginner)
Puppet
 
Puppetcamp module design talk
Puppetcamp module design talkPuppetcamp module design talk
Puppetcamp module design talk
Jeremy Kitchen
 
vfsStream - effective filesystem mocking
vfsStream - effective filesystem mocking vfsStream - effective filesystem mocking
vfsStream - effective filesystem mocking Sebastian Marek
 
Maze
MazeMaze
Maze
yito24
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slidesharetomcopeland
 
"Continuously delivering infrastructure using Terraform and Packer" training ...
"Continuously delivering infrastructure using Terraform and Packer" training ..."Continuously delivering infrastructure using Terraform and Packer" training ...
"Continuously delivering infrastructure using Terraform and Packer" training ...
Anton Babenko
 

Similar to はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech (20)

Centos config
Centos configCentos config
Centos config
 
If love is_blind_-_tiffany
If love is_blind_-_tiffanyIf love is_blind_-_tiffany
If love is_blind_-_tiffany
 
Crushing React bugs with Jest and Enzyme
Crushing React bugs with Jest and EnzymeCrushing React bugs with Jest and Enzyme
Crushing React bugs with Jest and Enzyme
 
Exercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera CymbronExercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera Cymbron
 
Advance Java Programs skeleton
Advance Java Programs skeletonAdvance Java Programs skeleton
Advance Java Programs skeleton
 
Node.js basics
Node.js basicsNode.js basics
Node.js basics
 
NodeJs
NodeJsNodeJs
NodeJs
 
Spring data iii
Spring data iiiSpring data iii
Spring data iii
 
こわくないよ❤️ Playframeworkソースコードリーディング入門
こわくないよ❤️ Playframeworkソースコードリーディング入門こわくないよ❤️ Playframeworkソースコードリーディング入門
こわくないよ❤️ Playframeworkソースコードリーディング入門
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
 
Txjs
TxjsTxjs
Txjs
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Hadoop
HadoopHadoop
Hadoop
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
 
Puppet Camp LA 2015: Basic Puppet Module Design (Beginner)
Puppet Camp LA  2015: Basic Puppet Module Design (Beginner)Puppet Camp LA  2015: Basic Puppet Module Design (Beginner)
Puppet Camp LA 2015: Basic Puppet Module Design (Beginner)
 
Puppetcamp module design talk
Puppetcamp module design talkPuppetcamp module design talk
Puppetcamp module design talk
 
vfsStream - effective filesystem mocking
vfsStream - effective filesystem mocking vfsStream - effective filesystem mocking
vfsStream - effective filesystem mocking
 
Maze
MazeMaze
Maze
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
 
"Continuously delivering infrastructure using Terraform and Packer" training ...
"Continuously delivering infrastructure using Terraform and Packer" training ..."Continuously delivering infrastructure using Terraform and Packer" training ...
"Continuously delivering infrastructure using Terraform and Packer" training ...
 

More from Tomohiro Kumagai

最近気づいた勉強法 — 勉強会開催の習慣化 #yumemi_grow
最近気づいた勉強法 — 勉強会開催の習慣化 #yumemi_grow最近気づいた勉強法 — 勉強会開催の習慣化 #yumemi_grow
最近気づいた勉強法 — 勉強会開催の習慣化 #yumemi_grow
Tomohiro Kumagai
 
Swift 所有権 要諦 #ゆるちとせ
Swift 所有権 要諦 #ゆるちとせSwift 所有権 要諦 #ゆるちとせ
Swift 所有権 要諦 #ゆるちとせ
Tomohiro Kumagai
 
_Function Builders in Swift #love_swift
_Function Builders in Swift #love_swift_Function Builders in Swift #love_swift
_Function Builders in Swift #love_swift
Tomohiro Kumagai
 
Property Wrappers の特徴を眺める #swiftzoomin
Property Wrappers の特徴を眺める #swiftzoominProperty Wrappers の特徴を眺める #swiftzoomin
Property Wrappers の特徴を眺める #swiftzoomin
Tomohiro Kumagai
 
みんなで Swift 復習会 GO! in "Swift Days Fukuoka" – 12nd′ オープニング&資料
みんなで Swift 復習会 GO! in "Swift Days Fukuoka" – 12nd′ オープニング&資料みんなで Swift 復習会 GO! in "Swift Days Fukuoka" – 12nd′ オープニング&資料
みんなで Swift 復習会 GO! in "Swift Days Fukuoka" – 12nd′ オープニング&資料
Tomohiro Kumagai
 
みんなで Swift 復習会
GO! in 札幌 – 10th′′
みんなで Swift 復習会
GO! in 札幌 – 10th′′みんなで Swift 復習会
GO! in 札幌 – 10th′′
みんなで Swift 復習会
GO! in 札幌 – 10th′′
Tomohiro Kumagai
 
イニシャライザー Part 2.5 #hakataswift
イニシャライザー Part 2.5 #hakataswiftイニシャライザー Part 2.5 #hakataswift
イニシャライザー Part 2.5 #hakataswift
Tomohiro Kumagai
 
ニコニコ超会議・文化の交差点 #techpub #ニコニコ超会議 #さくらシンデレラ
ニコニコ超会議・文化の交差点 #techpub #ニコニコ超会議 #さくらシンデレラニコニコ超会議・文化の交差点 #techpub #ニコニコ超会議 #さくらシンデレラ
ニコニコ超会議・文化の交差点 #techpub #ニコニコ超会議 #さくらシンデレラ
Tomohiro Kumagai
 
Swift クラスのイニシャライザー #devsap
Swift クラスのイニシャライザー #devsapSwift クラスのイニシャライザー #devsap
Swift クラスのイニシャライザー #devsap
Tomohiro Kumagai
 
iOSCon 2019 in London #ioscon #love_swift
iOSCon 2019 in London #ioscon #love_swiftiOSCon 2019 in London #ioscon #love_swift
iOSCon 2019 in London #ioscon #love_swift
Tomohiro Kumagai
 
Around the 変数 let #love_swift
Around the 変数 let #love_swiftAround the 変数 let #love_swift
Around the 変数 let #love_swift
Tomohiro Kumagai
 
もくもく執筆会 #技術同人誌再販Night
もくもく執筆会 #技術同人誌再販Nightもくもく執筆会 #技術同人誌再販Night
もくもく執筆会 #技術同人誌再販Night
Tomohiro Kumagai
 
みんなで Swift 復習会 GO! in 岩手 – 9th′
みんなで Swift 復習会 GO! in 岩手 – 9th′みんなで Swift 復習会 GO! in 岩手 – 9th′
みんなで Swift 復習会 GO! in 岩手 – 9th′
Tomohiro Kumagai
 
macOS アプリで Swift Package Manager を使ってみる #love_swift #hakataswift
macOS アプリで Swift Package Manager を使ってみる #love_swift #hakataswiftmacOS アプリで Swift Package Manager を使ってみる #love_swift #hakataswift
macOS アプリで Swift Package Manager を使ってみる #love_swift #hakataswift
Tomohiro Kumagai
 
みんなで Swift 復習会 GO! in 福岡 – 8th′ #minna_de_swift
みんなで Swift 復習会 GO! in 福岡 – 8th′ #minna_de_swiftみんなで Swift 復習会 GO! in 福岡 – 8th′ #minna_de_swift
みんなで Swift 復習会 GO! in 福岡 – 8th′ #minna_de_swift
Tomohiro Kumagai
 
Getting Started with Attending iOSCon in London 高画質・追記版 #love_swift #ioscon
Getting Started with Attending iOSCon in London 高画質・追記版 #love_swift #iosconGetting Started with Attending iOSCon in London 高画質・追記版 #love_swift #ioscon
Getting Started with Attending iOSCon in London 高画質・追記版 #love_swift #ioscon
Tomohiro Kumagai
 
みんなで Swift 復習会
GO! in 京都 – 6th′
みんなで Swift 復習会
GO! in 京都 – 6th′みんなで Swift 復習会
GO! in 京都 – 6th′
みんなで Swift 復習会
GO! in 京都 – 6th′
Tomohiro Kumagai
 
みんなで Swift 復習会 GO! in 福岡 – 5th′
みんなで Swift 復習会 GO! in 福岡 – 5th′みんなで Swift 復習会 GO! in 福岡 – 5th′
みんなで Swift 復習会 GO! in 福岡 – 5th′
Tomohiro Kumagai
 
勉強会の東京外開催の気持ち #yuru_bounen2017
勉強会の東京外開催の気持ち #yuru_bounen2017勉強会の東京外開催の気持ち #yuru_bounen2017
勉強会の東京外開催の気持ち #yuru_bounen2017
Tomohiro Kumagai
 
みんなで Swift 復習会 GO! in 福岡・発表資料
みんなで Swift 復習会 GO! in 福岡・発表資料みんなで Swift 復習会 GO! in 福岡・発表資料
みんなで Swift 復習会 GO! in 福岡・発表資料
Tomohiro Kumagai
 

More from Tomohiro Kumagai (20)

最近気づいた勉強法 — 勉強会開催の習慣化 #yumemi_grow
最近気づいた勉強法 — 勉強会開催の習慣化 #yumemi_grow最近気づいた勉強法 — 勉強会開催の習慣化 #yumemi_grow
最近気づいた勉強法 — 勉強会開催の習慣化 #yumemi_grow
 
Swift 所有権 要諦 #ゆるちとせ
Swift 所有権 要諦 #ゆるちとせSwift 所有権 要諦 #ゆるちとせ
Swift 所有権 要諦 #ゆるちとせ
 
_Function Builders in Swift #love_swift
_Function Builders in Swift #love_swift_Function Builders in Swift #love_swift
_Function Builders in Swift #love_swift
 
Property Wrappers の特徴を眺める #swiftzoomin
Property Wrappers の特徴を眺める #swiftzoominProperty Wrappers の特徴を眺める #swiftzoomin
Property Wrappers の特徴を眺める #swiftzoomin
 
みんなで Swift 復習会 GO! in "Swift Days Fukuoka" – 12nd′ オープニング&資料
みんなで Swift 復習会 GO! in "Swift Days Fukuoka" – 12nd′ オープニング&資料みんなで Swift 復習会 GO! in "Swift Days Fukuoka" – 12nd′ オープニング&資料
みんなで Swift 復習会 GO! in "Swift Days Fukuoka" – 12nd′ オープニング&資料
 
みんなで Swift 復習会
GO! in 札幌 – 10th′′
みんなで Swift 復習会
GO! in 札幌 – 10th′′みんなで Swift 復習会
GO! in 札幌 – 10th′′
みんなで Swift 復習会
GO! in 札幌 – 10th′′
 
イニシャライザー Part 2.5 #hakataswift
イニシャライザー Part 2.5 #hakataswiftイニシャライザー Part 2.5 #hakataswift
イニシャライザー Part 2.5 #hakataswift
 
ニコニコ超会議・文化の交差点 #techpub #ニコニコ超会議 #さくらシンデレラ
ニコニコ超会議・文化の交差点 #techpub #ニコニコ超会議 #さくらシンデレラニコニコ超会議・文化の交差点 #techpub #ニコニコ超会議 #さくらシンデレラ
ニコニコ超会議・文化の交差点 #techpub #ニコニコ超会議 #さくらシンデレラ
 
Swift クラスのイニシャライザー #devsap
Swift クラスのイニシャライザー #devsapSwift クラスのイニシャライザー #devsap
Swift クラスのイニシャライザー #devsap
 
iOSCon 2019 in London #ioscon #love_swift
iOSCon 2019 in London #ioscon #love_swiftiOSCon 2019 in London #ioscon #love_swift
iOSCon 2019 in London #ioscon #love_swift
 
Around the 変数 let #love_swift
Around the 変数 let #love_swiftAround the 変数 let #love_swift
Around the 変数 let #love_swift
 
もくもく執筆会 #技術同人誌再販Night
もくもく執筆会 #技術同人誌再販Nightもくもく執筆会 #技術同人誌再販Night
もくもく執筆会 #技術同人誌再販Night
 
みんなで Swift 復習会 GO! in 岩手 – 9th′
みんなで Swift 復習会 GO! in 岩手 – 9th′みんなで Swift 復習会 GO! in 岩手 – 9th′
みんなで Swift 復習会 GO! in 岩手 – 9th′
 
macOS アプリで Swift Package Manager を使ってみる #love_swift #hakataswift
macOS アプリで Swift Package Manager を使ってみる #love_swift #hakataswiftmacOS アプリで Swift Package Manager を使ってみる #love_swift #hakataswift
macOS アプリで Swift Package Manager を使ってみる #love_swift #hakataswift
 
みんなで Swift 復習会 GO! in 福岡 – 8th′ #minna_de_swift
みんなで Swift 復習会 GO! in 福岡 – 8th′ #minna_de_swiftみんなで Swift 復習会 GO! in 福岡 – 8th′ #minna_de_swift
みんなで Swift 復習会 GO! in 福岡 – 8th′ #minna_de_swift
 
Getting Started with Attending iOSCon in London 高画質・追記版 #love_swift #ioscon
Getting Started with Attending iOSCon in London 高画質・追記版 #love_swift #iosconGetting Started with Attending iOSCon in London 高画質・追記版 #love_swift #ioscon
Getting Started with Attending iOSCon in London 高画質・追記版 #love_swift #ioscon
 
みんなで Swift 復習会
GO! in 京都 – 6th′
みんなで Swift 復習会
GO! in 京都 – 6th′みんなで Swift 復習会
GO! in 京都 – 6th′
みんなで Swift 復習会
GO! in 京都 – 6th′
 
みんなで Swift 復習会 GO! in 福岡 – 5th′
みんなで Swift 復習会 GO! in 福岡 – 5th′みんなで Swift 復習会 GO! in 福岡 – 5th′
みんなで Swift 復習会 GO! in 福岡 – 5th′
 
勉強会の東京外開催の気持ち #yuru_bounen2017
勉強会の東京外開催の気持ち #yuru_bounen2017勉強会の東京外開催の気持ち #yuru_bounen2017
勉強会の東京外開催の気持ち #yuru_bounen2017
 
みんなで Swift 復習会 GO! in 福岡・発表資料
みんなで Swift 復習会 GO! in 福岡・発表資料みんなで Swift 復習会 GO! in 福岡・発表資料
みんなで Swift 復習会 GO! in 福岡・発表資料
 

Recently uploaded

A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
Aftab Hussain
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
Aftab Hussain
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Deuglo Infosystem Pvt Ltd
 
AI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website CreatorAI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website Creator
Google
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
Google
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Neo4j
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
Neo4j
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
Alina Yurenko
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
lorraineandreiamcidl
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Łukasz Chruściel
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 

Recently uploaded (20)

A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
 
AI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website CreatorAI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website Creator
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 

はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech

  • 1.
  • 2.
  • 4.
  • 6.
  • 7.
  • 8.
  • 9. class HogeOperation { private(set) var isPrepared = false func prepare() { guard !isPrepared else { fatalError("prepare を複数回呼ばないこと") } isPrepared = true } }
  • 10. // Init 状態の HogeOperation を生成 let operation = HogeOperation<Init>() // 最初は prepared を呼べて準備完了したものを取得可能 let preparedOp = operation.prepared() // 準備が終われば prepared はビルドエラーで実行不可 preparedOp.prepared()
  • 11.
  • 12. // これで "操作状態を表現する型" を表現 protocol OperationState {} // 操作状態ごとにクラスを定義 class Init: OperationState {} class Prepared: OperationState {}
  • 13. // 型パラメーターで型に状態を付与 class HogeOperation<State: OperationState> { /* 今回は内部で、 型パラメーターを使わないのがポイント */ }
  • 14. extension HogeOperation where State: Init { // 準備を実行し、準備完了状態のインスタンスを返す func prepared() -> HogeOperation<Prepared> {…} } extension HogeOperation where State: Prepared { // 目的の操作を実行する func execute() {…} }
  • 15.
  • 16. let operation = HogeOperation<Init>() // Init 状態では、まだ execute は存在しない operation.execute() // prepared を呼ぶことで Prepared 状態のものを取得 let preparedOp = operation.prepared() // Prepared 状態には、もう prepared は存在しない preparedOp.prepared()
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22. let operation = HogeOperation<Init>() // HogeOperation<Init> 型だから prepared が呼べる let preparedOp: HogeOperation<Prepared>() = operation.prepared() // HogeOperation<Prepared> 型だから execute が呼べる preparedOp.execute() // Init クラスや Prepared クラスを、実行時には使わない // ビルドの段階で、もう役目が済んでいる
  • 23.
  • 24. let operation = HogeOperation<Init>() let preparedOp = operation.prepared() let type1 = type(of: operation) let type2 = type(of: preparedOp) type1 == type2 // false
  • 25. // 型パラメーターで型に状態を付与 class HogeOperation<State: OperationState> { /* 内部では、型パラメーターを使っていない 型の在り方を説明するためだけに使っている */
  • 26.
  • 27. /// Phantom Type に出逢う前の認識 // Array はテンプレート的なもので… struct Array<Element> { } // 型パラメーターによって、異なる型になる let values: Array<Int> = Array<String>()
  • 28.
  • 29. // protocol OperationState {} // class Init: OperationState {} // class Prepared: OperationState {}
  • 30. class Operation { fileprivate var data: OperationData fileprivate init(data: OperationData) { self.data = data } func mob() {} }
  • 31. class OperationInit: Operation { convenience init() {…} func prepared() -> OperationPrepared {…} } class OperationPrepared: Operation { func execute() {…} }
  • 32. let operation = OperationInit() let preparedOp = operation.prepared() preparedOp.execute()
  • 33.
  • 34. struct OperationInit { fileprivate var data: OperationData fileprivate init(data: OperationData) {…} // 共通機能 func mob() {} // 固有の機能 init() {…} func prepared() -> OperationPrepared {…} }
  • 35. struct OperationPrepared { fileprivate var data: OperationData fileprivate init(data: OperationData) {…} // 共通機能 func mob() {} // 固有の機能 func execute() {…} }
  • 36. let operation = OperationInit() let preparedOp = operation.prepared() preparedOp.execute()
  • 37. protocol Operation {} struct OperationInit: Operation { … } struct OperationPrepared: Operation { … }
  • 38.
  • 39. struct Operation { struct Init { … } struct Prepared { … } }
  • 40. let operation = Operation.Init() let preparedOp = operation.prepared() preparedOp.execute()
  • 41.
  • 42. class Operation { fileprivate var data: OperationData fileprivate init(data: OperationData) { self.data = data } func mob() {} }
  • 43. extension Operation { class Init: Operation { … } class Prepared: Operation { … } }
  • 44. let operation = Operation.Init() let preparedOp = operation.prepared() preparedOp.execute()
  • 45.
  • 46.
  • 47.
  • 48.
  • 49. class HogeOperation<State: OperationState> { func mob() {…} } extension HogeOperation where State: Init { func prepared() -> HogeOperation<Prepared> {…} } extension HogeOperation where State: Prepared { func execute() {…} }
  • 50. let operation = HogeOperation<Init>() operation.execute()
  • 51. let operation = OperationInit() operation.execute()
  • 52.
  • 54. protocol Operation {} class HogeOperation<State: OperationState>: Operation { } var op: Operation op = HogeOperation<Init>() op = (op as! HogeOperation<Init>).prepared() op = (op as! HogeOperation<Prepared>).execute()
  • 55.
  • 56. class Driver { init(channel: Int? = nil, volume: Int? = nil, pan: Int? = nil, format: Format? = nil, route: Route? = nil) { } } // 設定項目に何があるかや、設定順番に気を使う let driver = Driver(volume: 10, format: ulaw, route: .speaker)
  • 57. // 本体のクラスを Phantom Type で定義して… class Driver<State> where State: AudioState { } // 準備が整ったときの機能を実装し… extension Driver where State: Ready { func start() { … } }
  • 58. // 初期化中にできることを規定すると… extension Driver where State: Setup { func prepared() -> Driver<Ready> { … } func set(channel: Int) -> Driver { return self } func set(volume: Int) -> Driver { return self } func set(pan: Int) -> Driver { return self } func set(format: Format) -> Driver { return self } func set(route: Route) -> Driver { return self } }
  • 59. // 初期設定では、順番を気にせず設定できる・補完が効く let driver = Driver<Setup>() .set(format: ulaw) .set(volume: 10) .set(route: .speaker) .prepared() // ここで Driver<Ready>() を返す // 設定完了を宣言 (prepared) して、使い始める driver.start()
  • 60. let driver = Driver<Setup>() .format // → Driver<FormatSetup> .set(sampleRate: 44100) .set(channelsPerFrame: 2) .general // → Driver<GeneralSetup> .set(volume: 10) .set(route: .speaker) .prepared() // → Driver<Ready>
  • 61. let driver = Driver.setup() // → DriverSetup .format // → FormatSetup .set(sampleRate: 44100) .set(channelsPerFrame: 2) .general // → AudioSetup .set(volume: 10) .set(route: .speaker) .prepared() // → Driver
  • 62.
  • 63. // 設定項目を、初期値を持った構造体で用意して… struct Description { var channel: Int = default var volume: Int = default var pan: Int = default var format: Format = default var route: Route = default }
  • 64. let description = Description() description.format.sampleRate = 44100 description.format.channelsPerFrame = 2 description.volume = 10 description.route = .speaker
  • 65. // Driver は Description で初期化するようにして… class Driver { init(description: Description) { … } } // 設定項目を渡して、初期化を完成する let driver = Driver(description: description)
  • 66.
  • 67.
  • 68. class Controller { var environment: Environment<Neutral> }
  • 69. struct Environment<State> { fileprivate(set) var platform: Platform fileprivate(set) var version: Double func startEditing() -> Environment<Editing> { return Environment<Editing>( platform: platform, version: version) } }
  • 70. extension Environment where State: Editing { mutating func set(platform: Platform) { … } mutating func set(version: Double) { … } func endEditing() -> Environment<Neutral> { return Environment<Neutral>( platform: platform, version: version) } }
  • 71. func update() { // 編集状態で取り出さないと、書き込めない var environment = self.environment.startEditing() environment.set(platform: .macOS) environment.set(version: Platform.macOS.latest) // ローカルで編集を終了したら、書き戻す self.environment = environment.endEditing() }
  • 72.
  • 73. extension Environment where State: Editing { var platform: Platform var version: Double // 同じ内容の、別インスタンスを作り直している func endEditing() -> Environment<Neutral> { return Environment<Neutral>( platform: platform, version: version) }
  • 74. extension Environment where State: Editing { // 内容を原始的にコピーしないといけないとき func endEditing() -> Environment<Neutral> { var result = Environment<Neutral>() result.platform = platform result.version = version return result }
  • 75.
  • 76. struct Environment<State> { fileprivate(set) var platform: Platform fileprivate(set) var version: Double } extension Environment { fileprivate init<S>(takeover: Environment<S>) { platform = takeover.platform version = takeover.version } }
  • 77. extension Environment where State: Editing { func endEditing() -> Environment<Neutral> { return Environment<Neutral>(takeover: self) } }
  • 78.
  • 79. struct Environment<State> { // データをここで集中管理する fileprivate struct Context { var platform: Platform var version: Double } // これだけを引き継げば済む状況を作る fileprivate var _context: Context }
  • 80. extension Environment { fileprivate init(context: Context) { _context = context } }
  • 81. extension Environment where State: Editing { func endEditing() -> Environment<Neutral> { return Environment<Neutral>(context: _context) } }
  • 82. extension Environment { var platform: Platform { get { _context.platform } set { _context.platform = newValue } } var version: Double { get { _context.version } set { _context.version = newValue } }
  • 83.
  • 84. extension Environment where State: Editing { func endEditing() -> Environment<Neutral> { // 準備不要で、いきなりビットキャスト可能 return unsafeBitCast(self, to: Environment<Neutral>.self) } }
  • 85. extension Environment { fileprivate init<S>(takeover: Environment<S>) { self = unsafeBitCast(takeover, to: Environment.self) } }
  • 86. let sub: Base = Sub() let base: Base = Base() // 実体が Sub なので、全ての機能が使える let obj: Sub = unsafeBitCast(sub, to: Sub.self) // 実体が Base なので、Sub の機能を使うとクラッシュする let obj: Sub = unsafeBitCast(base, to: Sub.self)
  • 87.
  • 88.
  • 89. class Test: OperationState {} extension HogeOperation where State: Test { func testSomething() {…} } extension HogeOperation where State: Init { func testing() -> HogeOperation<Test> {…} }
  • 90.
  • 91. // Test 状態を Prepared から継承させれば… class Test: Prepared {} // Test には Prepared の機能も備わる extension HogeOperation where State: Prepared { func execute() {…} } extension HogeOperation where State: Test { func testSomething() {…} }