SlideShare a Scribd company logo
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

More Related Content

PDF
map関数の内部実装から探るJVM言語のコレクション: Scala, Kotlin, Clojureコレクションの基本的な設計を理解しよう
PDF
関数型言語テイスティング: Haskell, Scala, Clojure, Elixirを比べて味わう関数型プログラミングの旨さ
ODP
これから Haskell を書くにあたって
PDF
Scalaプログラミング・マニアックス
PDF
From Scala/Clojure to Kotlin
PDF
これから Haskell を書くにあたって
PDF
BOF1-Scala02.pdf
PDF
BOF1-Scala02.pdf
map関数の内部実装から探るJVM言語のコレクション: Scala, Kotlin, Clojureコレクションの基本的な設計を理解しよう
関数型言語テイスティング: Haskell, Scala, Clojure, Elixirを比べて味わう関数型プログラミングの旨さ
これから Haskell を書くにあたって
Scalaプログラミング・マニアックス
From Scala/Clojure to Kotlin
これから Haskell を書くにあたって
BOF1-Scala02.pdf
BOF1-Scala02.pdf

Similar to do Notation Equivalents in JVM languages: Scala, Kotlin, Clojure (20)

PDF
BOF1-Scala02.pdf
PDF
たのしい関数型
PDF
プログラミング言語Scala
KEY
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
KEY
モナドがいっぱい!
PDF
Freer Monads, More Extensible Effects
PDF
15分でざっくり分かるScala入門
PDF
モナドハンズオン前座
PDF
Object-Funcational Analysis and design
PDF
すごいH 第12章モノイド
PDF
Object-Functional Analysis and Design and Programming温泉
PDF
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
PDF
Haskell Lecture 2
PDF
Scala の関数型プログラミングを支える技術
PDF
Essential Scala 第5章 シーケンス処理
PDF
第2回関数型言語勉強会 大阪
PDF
すごいHaskell楽しく学ぼう-第12章モノイド-
PDF
F#入門 ~関数プログラミングとは何か~
PDF
オブジェクト指向開発におけるObject-Functional Programming
PDF
関数プログラミング入門
BOF1-Scala02.pdf
たのしい関数型
プログラミング言語Scala
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
モナドがいっぱい!
Freer Monads, More Extensible Effects
15分でざっくり分かるScala入門
モナドハンズオン前座
Object-Funcational Analysis and design
すごいH 第12章モノイド
Object-Functional Analysis and Design and Programming温泉
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
Haskell Lecture 2
Scala の関数型プログラミングを支える技術
Essential Scala 第5章 シーケンス処理
第2回関数型言語勉強会 大阪
すごいHaskell楽しく学ぼう-第12章モノイド-
F#入門 ~関数プログラミングとは何か~
オブジェクト指向開発におけるObject-Functional Programming
関数プログラミング入門
Ad

More from Kent Ohashi (20)

PDF
純LISPから考える関数型言語のプリミティブ: Clojure, Elixir, Haskell, Scala
PDF
TDD with RDD: Clojure/LispのREPLで変わる開発体験
PDF
🐬の推し本紹介2024: 『脱・日本語なまり 英語(+α)実践音声学』
PDF
Kotlin Meets Data-Oriented Programming: Kotlinで実践する「データ指向プログラミング」
PDF
RDBでのツリー表現入門2024
PDF
ミュータビリティとイミュータビリティの狭間: 関数型言語使いから見たKotlinコレクション
PDF
インターフェース定義言語から学ぶモダンなWeb API方式: REST, GraphQL, gRPC
PDF
Team Geek Revisited
PDF
Scala vs Clojure?: The Rise and Fall of Functional Languages in Opt Technologies
PDF
Clojureコレクションで探るimmutableでpersistentな世界
PDF
英語学習者のためのフランス語文法入門: フランス語完全理解(?)
PDF
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
PDF
実用のための語源学入門
PDF
メタプログラミング入門
PDF
労働法の世界
PDF
Clojureで作る"simple"なDSL
PDF
RDBでのツリー表現入門
PDF
GraphQL入門
PDF
Everyday Life with clojure.spec
PDF
たのしい多言語学習
純LISPから考える関数型言語のプリミティブ: Clojure, Elixir, Haskell, Scala
TDD with RDD: Clojure/LispのREPLで変わる開発体験
🐬の推し本紹介2024: 『脱・日本語なまり 英語(+α)実践音声学』
Kotlin Meets Data-Oriented Programming: Kotlinで実践する「データ指向プログラミング」
RDBでのツリー表現入門2024
ミュータビリティとイミュータビリティの狭間: 関数型言語使いから見たKotlinコレクション
インターフェース定義言語から学ぶモダンなWeb API方式: REST, GraphQL, gRPC
Team Geek Revisited
Scala vs Clojure?: The Rise and Fall of Functional Languages in Opt Technologies
Clojureコレクションで探るimmutableでpersistentな世界
英語学習者のためのフランス語文法入門: フランス語完全理解(?)
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
実用のための語源学入門
メタプログラミング入門
労働法の世界
Clojureで作る"simple"なDSL
RDBでのツリー表現入門
GraphQL入門
Everyday Life with clojure.spec
たのしい多言語学習
Ad

do Notation Equivalents in JVM languages: Scala, Kotlin, Clojure