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
do Notation Equivalents in JVM languages: Scala...
Search
Kent OHASHI
November 22, 2024
Programming
0
23
do Notation Equivalents in JVM languages: Scala, Kotlin, Clojure
Haskellでお馴染みのdo記法(do notation)がJVM言語Scala, Kotlin, Clojureでは言語機能やライブラリ実装としてどのように実現されているか、簡単に探ってみよう。
Kent OHASHI
November 22, 2024
Tweet
Share
More Decks by Kent OHASHI
See All by Kent OHASHI
TDD with RDD: Changed Developer Experience through Clojure/Lisp REPLs
lagenorhynque
0
15
My Favourite Book in 2024: Get Rid of Your Japanese Accent
lagenorhynque
0
26
Exploring Collections in JVM Languages through Internals of map Function
lagenorhynque
0
27
Kotlin Meets Data-Oriented Programming
lagenorhynque
0
32
Introduction to Tree Representations in RDB 2024
lagenorhynque
0
49
Boundary between Mutability and Immutability
lagenorhynque
0
59
Learning Modern Web API Styles from IDL: REST, GraphQL, gRPC
lagenorhynque
0
96
Team Geek Revisited
lagenorhynque
0
76
Scala vs Clojure?: The Rise and Fall of Functional Languages in Opt Technologies
lagenorhynque
0
140
Other Decks in Programming
See All in Programming
Moscow Python Meetup №97. Константин Крестников (Техлид команды GigaChain (SberDevices)). GigaChain: Новые инструменты для разработки агентов на примере агента техподдержки
moscowdjango
PRO
0
100
[JAWS-UG横浜 #80] うわっ…今年のServerless アップデート、少なすぎ…?
maroon1st
0
150
為你自己學 Python
eddie
0
540
Fibonacci Function Gallery - Part 2
philipschwarz
PRO
0
230
盆栽転じて家具となる / Bonsai and Furnitures
aereal
0
2.2k
AHC041解説
terryu16
0
550
Запуск 1С:УХ в крупном энтерпрайзе: мечта и реальность ПМа
lamodatech
0
990
動作確認やテストで漏れがちな観点3選
starfish719
5
870
BEエンジニアがFEの業務をできるようになるまでにやったこと
yoshida_ryushin
0
260
Alba: Why, How and What's So Interesting
okuramasafumi
0
240
法律の脱レガシーに学ぶフロントエンド刷新
oguemon
4
620
SwiftUIで単方向アーキテクチャを導入して得られた成果
takuyaosawa
0
140
Featured
See All Featured
Thoughts on Productivity
jonyablonski
68
4.4k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
3
270
The Invisible Side of Design
smashingmag
299
50k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.2k
How to Think Like a Performance Engineer
csswizardry
22
1.3k
Making the Leap to Tech Lead
cromwellryan
133
9.1k
Designing Experiences People Love
moore
139
23k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
Making Projects Easy
brettharned
116
6k
Product Roadmaps are Hard
iamctodd
PRO
50
11k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
160
15k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
113
50k
Transcript
do Notation Equivalents in JVM languages: Scala, Kotlin, Clojure 1
のシニアエンジニア スタートアップの起業家と投資家のための業務効 率化 連携プラットフォームを開発している 主要技術スタック の運営企業 などの関数型⾔語と関数型プログ ラミングの実践が好き と ⾔語での開発実務
に⻑く取り組んできた lagénorhynque カマイルカ 株式会社スマートラウンド 2
での発表テーマ JJUG CCC 2024 Fall map関数の内部実装から探るJVM⾔語のコレクション 3
Haskellの do 記法 4
モナドを扱い始めると >>= (bind)演算⼦がネストして いく(⼀種のcallback hell) 先⾏する計算の⽂脈を引き継ぐという意味では⾃然な 表現かも 読み書きにはあまり優しくないが λ> :{
λ| -- 例としてMaybe λ| Just 2 >>= \x -> λ| Just 10 >>= \y -> λ| return $ x ^ y λ| :} Just 1024 it :: Num b => Maybe b 5
簡潔に書き換える構⽂として do 記法がある のように ネストしたコードではなく 命令型の プログラム⾵のフラットなコードになる λ> :{ λ|
do λ| x <- Just 2 λ| y <- Just 10 λ| return $ x ^ y λ| :} Just 1024 it :: Num b => Maybe b λ> :{ -- リストに対しても同様に λ| do λ| x <- [1, 2, 3] λ| y <- [4, 5] λ| return $ x * y λ| :} [4,5,8,10,12,15] it :: Num b => [b]
Scalaの場合 7
モナドに相当する構造を扱い始めると flatMap, map がネストしていく // 例としてOption scala> Some(2).flatMap(x => |
Some(10).map(y => | scala.math.pow(x, y).toInt | ) | ) val res0: Option[Int] = Some(1024) 8
簡潔に書き換える構⽂として for 式がある scala> for | x <- Some(2) |
y <- Some(10) | yield scala.math.pow(x, y).toInt val res1: Option[Int] = Some(1024) // Seqに対しても同様に scala> for | x <- Seq(1, 2, 3) | y <- Seq(4, 5) | yield x * y val res2: Seq[Int] = List(4, 5, 8, 10, 12, 15) 9
Kotlinの場合 10
nullable (nullになりうる値)に対して >>> import kotlin.math.pow >>> (2.0 as Double?)?.let {
x -> ... (10.0 as Double?)?.let { y -> ... x.pow(y).toInt() ... } ... } res1: kotlin.Int = 1024 11
Iterableに対して >>> listOf(1, 2, 3).flatMap { x -> ... listOf(4,
5).map { y -> ... x * y ... } ... } res2: kotlin.collections.List<kotlin.Int> = [4, 5, 8, 10, 12, 15] 12
ライブラリ の 関数を利⽤する Arrow nullable import arrow.core.raise.nullable import kotlin.math.pow nullable
{ val x = (2.0 as Double?).bind() val y = (10.0 as Double?).bind() x.pow(y).toInt() } 13
ライブラリでの実例 らしく関数型の設計パターンを実装し ているライブラリ 関数 関数 関数 関数 関数 モナドライブラリ 関数
14
Clojureの場合 15
nilable (nilになりうる値)に対して user> (when-let [x 2] (when-let [y 10] (long
(clojure.math/pow x y)))) 1024 16
seqable (シーケンス化できる値)に対して ;; mapcat (= map + concat)とmap user> (mapcat
(fn [x] (map (fn [y] (* x y)) [4 5])) [1 2 3]) (4 5 8 10 12 15) ;; forマクロ(内包表記) user> (for [x [1 2 3] y [4 5]] (* x y)) (4 5 8 10 12 15) 17
モナドをプロトコルとして抽象化してみる (defprotocol Monad (return [this x]) (bind [this f m]))
18
do記法相当の構⽂をマクロとして定義する (defmacro mlet [monad bindings & body] (if-some [[sym m
& bindings] (seq bindings)] `(bind ~monad (fn [~sym] (mlet ~monad ~bindings ~@body)) ~m) `(return ~monad (do ~@body)))) 19
Monad プロトコルのメソッドに対する実装を与える ;; nilableに対する実装 (def nilable-monad (reify Monad (return [_
x] (identity x)) (bind [_ f m] (when (some? m) (f m))))) ;; seqableに対する実装 (def seqable-monad (reify Monad (return [_ x] (list x)) (bind [_ f m] (mapcat f m)))) 20
mlet マクロを使ってみる ;; nilable値の場合 do-notation> (mlet nilable-monad [x 2 y
10] (long (clojure.math/pow x y))) 1024 ;; seqable値の場合 do-notation> (mlet seqable-monad [x [1 2 3] y [4 5]] (* x y)) (4 5 8 10 12 15) 21
mlet マクロを使った式を展開してみる do-notation> (clojure.walk/macroexpand-all '(mlet ...省略...)) (do-notation/bind nilable-monad (fn* ([x]
(do-notation/bind nilable-monad (fn* ([y] (do-notation/return nilable-monad (do (long (clojure.math/pow x y)))))) 10))) 2) 22
ライブラリでの実例 の 実装 マクロ モナドライブラリ マクロ モナドを含む 圏論に由来する抽象 を扱うライブラリ マクロ
23
の 記法、 の 式が他⾔語でも たまにほしくなる メタプログラミングによる 構築は楽しい 24
Further Reading Haskell Scala 25
Kotlin 26
Clojure ドクセル 27