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
85
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
関数型言語テイスティング: Haskell, Scala, Clojure, Elixirを比べて味わう関数型プログラミングの旨さ
lagenorhynque
1
110
純LISPから考える関数型言語のプリミティブ: Clojure, Elixir, Haskell, Scala
lagenorhynque
1
120
From Scala/Clojure to Kotlin
lagenorhynque
0
52
TDD with RDD: Changed Developer Experience through Clojure/Lisp REPLs
lagenorhynque
0
84
My Favourite Book in 2024: Get Rid of Your Japanese Accent
lagenorhynque
1
120
map関数の内部実装から探るJVM言語のコレクション: Scala, Kotlin, Clojureコレクションの基本的な設計を理解しよう
lagenorhynque
0
78
Kotlin Meets Data-Oriented Programming
lagenorhynque
0
72
Introduction to Tree Representations in RDB 2024
lagenorhynque
0
100
Boundary between Mutability and Immutability
lagenorhynque
1
100
Other Decks in Programming
See All in Programming
ALL CODE BASE ARE BELONG TO STUDY
uzulla
27
6.6k
CSC305 Lecture 10
javiergs
PRO
0
220
Vueのバリデーション、結局どれを選べばいい? ― 自作バリデーションの限界と、脱却までの道のり ― / Which Vue Validation Library Should We Really Use? The Limits of Self-Made Validation and How I Finally Moved On
neginasu
2
760
Foundation Modelsを実装日本語学習アプリを作ってみた!
hypebeans
1
120
Catch Up: Go Style Guide Update
andpad
0
240
技術的負債の正体を知って向き合う
irof
0
230
TFLintカスタムプラグインで始める Terraformコード品質管理
bells17
2
350
Writing Better Go: Lessons from 10 Code Reviews
konradreiche
3
6.1k
Developer Joy - The New Paradigm
hollycummins
1
350
テーブル定義書の構造化抽出して、生成AIでDWH分析を試してみた / devio2025tokyo
kasacchiful
0
270
Google Opalで使える37のライブラリ
mickey_kubo
3
130
SwiftDataを使って10万件のデータを読み書きする
akidon0000
0
240
Featured
See All Featured
We Have a Design System, Now What?
morganepeng
53
7.8k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Practical Orchestrator
shlominoach
190
11k
Building Better People: How to give real-time feedback that sticks.
wjessup
369
20k
Navigating Team Friction
lara
190
15k
jQuery: Nuts, Bolts and Bling
dougneiner
65
7.9k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
10
610
Keith and Marios Guide to Fast Websites
keithpitt
411
23k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
630
The Cult of Friendly URLs
andyhume
79
6.6k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
34
2.3k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
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