Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
ビッグウェーブ到来!?
- 関数プログラミング導入の要点 -
粕谷大輔 (@daiksy)
PHPカンファレンス関西2015
2015-05-30
https://www.flickr.com/photos/48337143@N00/2664619137
粕谷 大輔
id:daiksy / @daiksy
株式会社 はてな
PHPカンファレンス2015
PHP歴
- 以前勤めていた会社で
社内SNSを導入
- Open PNE
PHPカンファレンス2015
以下のキーワードを学ぶ
- 副作用のないプログラム
- 参照透過性
今日のお話
☓ 関数型言語
⃝ 関数プログラミング
関数型言語
関数が第一級の対象である言語
Haskell
OCaml
LISP
関数プログラミング
いくつかの成約を守れば、
関数型言語以外でも可能。
関数型言語を学べば、
その知見を
フィードバックできる
でも
関数プログラミングって
難しそう。。。
(ラムダ?? モナド?? 圏論??)
確かに奥が深い
でもそれは
関数プログラミングに
限らないのでは?
今や誰もが知ってる
オブジェクト指向プログラミング
『オブジェクト指向入門』
2冊で約1700ページ
この本を全部読まないと
オブジェクト指向の入門は
完了しない?
そんなことはなさそう
関数プログラミングは
身近に実用的に使われるように
なってきた
感覚として、LLを習得してる人
は関数型言語に取っ付きやすい
という印象
今日はその
入り口を学ぶためのお話
- 副作用のないプログラム
- 参照透過性
副作用とは
ある機能がコンピュータの(論理的な)状態を変
化させ、それ以降で得られる結果に影響を与
えること
(wikipedia [副作用(プログラム)])
代表的な副作用
- 変数を変更する
- オブジェクトのフィールドを
設定する
- データ構造を直接変更する
バグの原因の大半は副作用
- 変数に意図しない値が入って
いた
- オブジェクトが意図しない状
態になっていた
- DBに意図しない値が…
副作用のないプログラム
副作用の影響範囲を局所化する
副作用の無い関数は常に意図ど
おりの結果が帰ってくる
副作用のないプログラムとは?
-> 参照透過性が保たれている
参照透過性とは??
難しい説明をすると
“式が参照透過であるということ
は、式をその結果に置き換えるこ
とができる”
例) 参照透過である場合
scala) val x = “Hello, World”
x: String = Hello, World
scala) val r1 = x.reverse
r1: String = dlroW ,olleH
scala) val r2 = x.reverse
r2: String = dlroW ,olleH
r1とr2の結果は同じ
コードは‘Functional Programming in scala’ より引用
例) 参照透過である場合
scala) val r2 = x.reverse
r2: String = dlroW ,olleH
scala) val r1 = “Hello, World”.reverse
r1:String = dlroW ,olleH
scala) val r2 = “Hello, World”.reverse
r2:String = dlroW ,olleH
変数xを、その式の結果である”Hello, World” と置き換えても
r1とr2の結果は同じ
-> 変数xは参照透過である
例) 参照透過でない場合
scala) val x = new StringBuilder(“Hello”)
x: StringBuilder = Hello
scala) val y = x.append(“, World”)
x: StringBuilder = Hello, World
scala) val r1 = y.toString
r1: String = Hello, World
scala) val r2 = y.toString
r2: String = Hello, World
r1 と r2の結果はここまでは同じ
例) 参照透過でない場合
scala) val x = new StringBuilder(“Hello”)
x: StringBuilder = Hello
scala) val y = x.append(“, World”)
x: StringBuilder = Hello, World
最初の例と同様に、y を x.append(“, World”) に置き換えてみよう
例) 参照透過でない場合
scala) val x = new StringBuilder(“Hello”)
x: StringBuilder = Hello
scala) val y = x.append(“, World”)
x: StringBuilder = Hello, World
scala) val r1 = x.append(“, World”).toString
r1: String = Hello, World
例) 参照透過でない場合
scala) val x = new StringBuilder(“Hello”)
x: StringBuilder = Hello
scala) val y = x.append(“, World”)
x: StringBuilder = Hello, World
scala) val r1 = x.append(“, World”).toString
r1: String = Hello, World
scala) val r2 = x.append(“, World”).toString
r2: String = Hello, World, World
変数を式に置き換えたことで結果が変わった -> 変数 y は参照透過でない
引数を10倍にして返す関数
-> 5を渡したら50
-> 6を渡したら60
参照透過である関数
参照透過である関数
• 何度呼び出しても常に同じ結果
• プログラマは内部の状態に気を配らずに気
軽にいつでも呼び出せる
引数をn倍にして返す関数
-> 5を渡したら5n
-> 6を渡したら6n
nの状態によって結果が変わる
参照透過でない関数
参照透過でない関数
• 呼び出すときの内部の状態によって結果が
変わる
• 関数を呼び出すときにプログラマが常に内
部の状態に気を配る必要がある
関数プログラミングとは
- 関数を組み合わせて計算を行
う
- 関数の結果が参照透過だから
安全にプログラムが書ける
副作用のないプログラミングとは
- 関数をできるだけ参照透過に
保つようにする
購入(商品ID, 個数, クレジットカード) {
- 商品テーブルをread
- 金額 <- 個数 単価
- 課金処理(金額, クレジットカード)
}
購入(商品ID, 個数, クレジットカード) {
- 商品テーブルをread
- 金額 <- 個数 単価
- 課金処理(金額, クレジットカード)
}
商品取得(商品ID){
- 商品テーブルをread
}
購入(商品, 個数) {
- 金額 <- 個数 単価
- 課金オブジェクト作成(金額)
}
課金処理(課金オブジェクト, クレジットカード)
まとめ (関数プログラミングの入口)
- 副作用を局所化することでバ
グの混入の余地を少なくする
- なるべく参照透過な関数を作っ
て計算することをこころがけ
よう
ご清聴
ありがとうございました

More Related Content

PHPカンファレンス2015