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
Option(al)が教えてくれたいろんな言語を知る楽しさ(というかひたすらOptionの解説)
Search
ihcomega56
May 13, 2017
Technology
0
1.8k
Option(al)が教えてくれたいろんな言語を知る楽しさ(というかひたすらOptionの解説)
Java女子部「Java x Scala交流会」
ihcomega56
May 13, 2017
Tweet
Share
More Decks by ihcomega56
See All by ihcomega56
JEP 455: Primitive Types in Patterns, instanceof, and switch (Preview)
ihcomega56
1
140
シリコンバレーのチームで経験したふりかえり - 共通点とギャップ / retrospectives in silicon valley
ihcomega56
5
1.9k
「サプライチェーン攻撃」に立ち向かう!SBOMを使った脆弱性管理がもたらす品質とスピード向上
ihcomega56
2
2.5k
アプリケーション開発者目線で語る、明日から始めるDevSecOps
ihcomega56
0
220
パターンマッチングを学んで新しいJavaの世界へ!Java 18までの目玉機能をおさらいしよう / Java 18 pattern matching
ihcomega56
3
1.4k
SCAとDockerを触ってみよう!DecSecOps入門ワークショップ / SCA and Docker workshop
ihcomega56
1
300
JFrogのDevOps Platformづくりを支えるオブザーバビリティ / JFrog Observability
ihcomega56
0
520
SBOMでソフトウェアを守れ!10年後も自信を持ってリリースするために今始めるDevSecOps / DevSecOps with SBOM for yourself 10 years from now
ihcomega56
1
6.5k
Javaアプリケーションの アーティファクト管理と DevSecOps / Java artifacts management and DevSecOps
ihcomega56
0
2.7k
Other Decks in Technology
See All in Technology
AI Agent Agentic Workflow の可観測性 / Observability of AI Agent Agentic Workflow
yuzujoe
0
180
技術選定、下から見るか?横から見るか?
masakiokuda
0
190
複雑さを受け入れるか、拒むか? - 事業成長とともに育ったモノリスを前に私が考えたこと #RSGT2026
murabayashi
1
1.8k
Databricks Free Edition講座 データエンジニアリング編
taka_aki
0
2.5k
【Agentforce Hackathon Tokyo 2025 発表資料】みらいシフト:あなた働き方を、みらいへシフト。
kuratani
0
120
ソフトとハード両方いけるデータ人材の育て方
waiwai2111
0
130
わが10年の叡智をぶつけたカオスなクラウドインフラが、なくなるということ。
sogaoh
PRO
1
500
Java 25に至る道
skrb
3
210
AI Agent Standards and Protocols: a Walkthrough of MCP, A2A, and more...
glaforge
0
190
会社紹介資料 / Sansan Company Profile
sansan33
PRO
11
390k
産業的変化も組織的変化も乗り越えられるチームへの成長 〜チームの変化から見出す明るい未来〜
kakehashi
PRO
1
530
ファインディにおけるフロントエンド技術選定の歴史
puku0x
2
1.4k
Featured
See All Featured
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.7k
Producing Creativity
orderedlist
PRO
348
40k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
1.8k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.3k
The Invisible Side of Design
smashingmag
302
51k
We Have a Design System, Now What?
morganepeng
54
8k
GraphQLの誤解/rethinking-graphql
sonatard
74
11k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
6.8k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.6k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
210
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Transcript
Option(al)が教えてくれた いろんな言語を知る楽しさ (というかひたすらOptionの解説) 2017.05.13 Java女子部 Java x Scala交流会
だれ • こな(@ihcomega) Java女子部の部長 明後日から会社が変わるよー 5月は春の登壇祭り!遊びに来てね JJUG CCC 2017 Spring
文系さえおさえれば英語を読む力は上がる! マチコ&河村の怒り新党 Java Day Tokyo 2017 Heather VanCura x Java女子部 ~海外と日本のエンジニア事情~ スペシャルパネルセッション - 海外Javaコミュニティ・エンジニア は今どんな活動をしているのか?
Java / Scalaエンジニアのみなさんと Option(al)をきっかけに 考え方を共有 = 交流 してみたいです! + 私が思ったことをお伝えします!
java.util.Optional 使ってますか? 何故この概念が便利か知ってますか?
Optionalと私 Java SE 8が出た当初、勉強してみたけど正直よく分 からなかった。 (「包む」「くるむ」「ラップする」の意味が分からずw) 理解する前に、Java離れを起こした。 大して触ったことのないまま放置!!!
scala.Option Javaで言うとOptionalに近いもの。 当たり前のように使われる!
Optionと私 実務でたくさん使った。 手を動かすことで便利さを実感し、身についた。 (本当はSwiftのOptionalもそうなんだけど今日は触れません…) 再び向き合い、理解出来た!
早速ScalaのOptionを紹介します!
Optionとは 存在するか分からない値を表現する ある ない OR
Optionとは 存在するか分からない値を表現する Scala.Some インスタンス None オブジェクト OR
例を使って考えてみましょう。
使うシーンを想定
使うシーンを想定 家がある
使うシーンを想定 家がある 家に本棚がある かもしれない
使うシーンを想定 家がある 家に本棚がある かもしれない 本棚に本がある かもしれない
使うシーンを想定 家がある 家に本棚がある かもしれない 本棚に本がある かもしれない ここで、 家の中にある本棚や本を扱う ことを考えてみる!
まずは必要なものを揃えましょう!
定義 イラストに登場したものたちをクラスで 定義してみる /** ຊ */ case class Book(title: String)
/** ຊ୨ */ case class BookShelf(book: Option[Book]) /** Ո */ case class House(bookShelf: Option[BookShelf])
定義 イラストに登場したものたちをクラスで 定義してみる /** ຊ */ case class Book(title: String)
/** ຊ୨ */ case class BookShelf(book: Option[Book]) /** Ո */ case class House(bookShelf: Option[BookShelf]) 家に本棚がある かもしれない 本棚に本がある かもしれない
インスタンス生成 本と本棚を用意しておく /** ίοϓຊ */ val scalaBook = Book("ίοϓຊ") /**
ຊͷஔ͔Εͨຊ୨ */ val fullShelf = BookShelf(Some(scalaBook)) /** ۭͷຊ୨ */ val emptyShelf = BookShelf(None)
インスタンス生成 3種類の家インスタンスを生成してみる /** ຊͷஔ͔Εͨຊ୨͕͋ΔՈ */ val houseWithFullShelf = House(Some(fullShelf)) /**
ۭͷຊ୨͕͋ΔՈ */ val houseWithEmptyShelf = House(Some(emptyShelf)) /** ຊ୨ͷͳ͍Ո */ val emptyHouse = House(None)
インスタンス生成 Optionの入れ子構造を確認しておく /** ຊͷஔ͔Εͨຊ୨͕͋ΔՈ */ val houseWithFullShelf = House(Some(BookShelf(Some(scalaBook)))) /**
ۭͷຊ୨͕͋ΔՈ */ val houseWithEmptyShelf = House(Some(BookShelf(None))) /** ຊ୨ͷͳ͍Ո */ val emptyHouse = House(None) つまり こういうこと
いよいよ値を取り出したり使ったりします。 よくわからない書き方や関数が出てくるかも しれませんが、操作のイメージを掴んでく ださい。
値を扱う方法 Option#get Option#getOrElse パターンマッチ Option#map Option#flatMap for式 ※ここにあるのは一部。他にも色々ある。 取り出して使う イメージ
Optionの中身を変換する イメージ
「取り出して使うイメージ」 の方からいきます。
Option#get 家から本棚を取り出してみる // ຊͷஔ͔Εͨຊ୨͕͋ΔՈ houseWithFullShelf.bookShelf.get
家から本棚を取り出してみる Option#get // ຊͷஔ͔Εͨຊ୨͕͋ΔՈ houseWithFullShelf.bookShelf.get res0: BookShelf = BookShelf(Some(Book(ίοϓຊ))) 取り出せた!
家から本棚を取り出してみる Option#get // ۭͷຊ୨͕͋ΔՈ houseWithEmptyShelf.bookShelf.get
家から本棚を取り出してみる Option#get // ۭͷຊ୨͕͋ΔՈ houseWithEmptyShelf.bookShelf.get res0: BookShelf = BookShelf(None) 取り出せた!
家から本棚を取り出してみる Option#get // ຊ୨͕ͳ͍Ո emptyHouse.bookShelf.get
家から本棚を取り出してみる Option#get // ຊ୨͕ͳ͍Ո emptyHouse.bookShelf.get java.util.NoSuchElementException: None.get 取り出せない!
家から本棚を取り出してみる Option#isDefined if (emptyHouse.bookShelf.isDefined) { emptyHouse.bookShelf.get } else { //
ུ } あるかな?
家から本棚を取り出してみる Option#isEmpty if (emptyHouse.bookShelf.isEmpty) { // ུ } else {
emptyHouse .bookShelf .get } ないかな?
それ 結局nullチェックと同じやん != null とか == null とか
Option#getの問題 安全に使うにはSomeであることを担保する必要が ある チェック漏れが発生したら死亡する 実行時までエラーに気付けない (つまりnullチェックと同じ問題を持ったまま・・・)
Option#getOrElse 本棚にある本のタイトルを取り出してみる // ຊͷஔ͔Εͨຊ୨ fullShelf.book.map(_.title).getOrElse("σϑΥϧτλΠτϧ") Some(“コップ本”) mapについては後述
Option#getOrElse // ຊͷஔ͔Εͨຊ୨ fullShelf.book.map(_.title).getOrElse("σϑΥϧτλΠτϧ") res0: String = ίοϓຊ 本が存在したので タイトルを
取り出せた! Some(“コップ本”) 本棚にある本のタイトルを取り出してみる
Option#getOrElse // ۭͷຊ୨ emptyShelf.book.map(_.title).getOrElse("σϑΥϧτλΠτϧ") None 本棚にある本のタイトルを取り出してみる
Option#getOrElse // ۭͷຊ୨ emptyShelf.book.map(_.title).getOrElse("σϑΥϧτλΠτϧ") res0: String = σϑΥϧτλΠτϧ None 本が存在しないので
デフォルト値を 返せた! 本棚にある本のタイトルを取り出してみる
// ຊͷஔ͔Εͨຊ୨ fullShelf.book match { case Some(b) => s"ʮ${b.title}ʯͱ͍͏ຊͩΑʂ" case
None => "λΠτϧ͕ݟ͔ͭΒͳ͍Αʼʻ" } パターンマッチ 本棚にある本のタイトルを取り出してみる
// ຊͷஔ͔Εͨຊ୨ fullShelf.book match { case Some(b) => s"ʮ${b.title}ʯͱ͍͏ຊͩΑʂ" case
None => "λΠτϧ͕ݟ͔ͭΒͳ͍Αʼʻ" } res0: String = ʮίοϓຊʯͱ͍͏ຊͩΑʂ 本が存在するので Someの場合の 結果が返された! パターンマッチ 本棚にある本のタイトルを取り出してみる
// ۭͷຊ୨ emptyShelf.book match { case Some(b) => s"ʮ${b.title}ʯͱ͍͏ຊͩΑʂ" case
None => "λΠτϧ͕ݟ͔ͭΒͳ͍Αʼʻ" } パターンマッチ 本棚にある本のタイトルを取り出してみる
// ۭͷຊ୨ emptyShelf.book match { case Some(b) => s"ʮ${b.title}ʯͱ͍͏ຊͩΑʂ" case
None => "λΠτϧ͕ݟ͔ͭΒͳ͍Αʼʻ" } res0: String = λΠτϧ͕ݟ͔ͭΒͳ͍Αʼʻ パターンマッチ 本が存在するので Noneの場合の 結果が返された! 本棚にある本のタイトルを取り出してみる
「Optionの中身を変換するイメージ」 の方いきます。
Option#map 本棚にある本をタイトルに変換してみる // ຊͷஔ͔Εͨຊ୨ fullShelf.book.map(_.title) 参考 map(b => b.title) とも書ける
本棚にある本をタイトルに変換してみる Option#map // ຊͷஔ͔Εͨຊ୨ fullShelf.book.map(_.title) res0: Option[String] = Some(ίοϓຊ) 本が存在したので
Someインスタンスとして タイトルが返された!
fullShelf.book.map(_.title) Option#map λΠτϧ λΠτϧ Option Option 本棚にある本をタイトルに変換してみる
fullShelf.book.map(_.title) Option#map λΠτϧ map λΠτϧ Option Option 本棚にある本をタイトルに変換してみる
Option#map // ۭͷຊ୨ emptyShelf.book.map(_.title) 本棚にある本をタイトルに変換してみる
Option#map // ۭͷຊ୨ emptyShelf.book.map(_.title) res0: Option[String] = None 本が存在しないので Noneオブジェクトが
返された! 本棚にある本をタイトルに変換してみる
Option#flatMap 家にある本棚を本に変換してみる // ຊͷஔ͔Εͨຊ୨͕͋ΔՈ houseWithFullShelf.bookShelf.flatMap(_.book)
家にある本棚を本に変換してみる // ຊͷஔ͔Εͨຊ୨͕͋ΔՈ houseWithFullShelf.bookShelf.flatMap(_.book) Option#flatMap res0: Option[Book] = Some(Book(ίοϓຊ)) 本棚・本が存在したので
Someインスタンスとして 本が返された!
houseWithFullShelf.bookShelf.flatMap(_.book) Option#flatMap Option Option Option Option 家にある本棚を本に変換してみる
家にある本棚を本に変換してみる houseWithFullShelf.bookShelf.flatMap(_.book) Option#flatMap flatMap Option Option Option
// ۭͷຊ୨͕͋ΔՈ houseWithEmptyShelf.bookShelf.flatMap(_.book) Option#flatMap 家にある本棚を本に変換してみる
// ۭͷຊ୨͕͋ΔՈ houseWithEmptyShelf.bookShelf.flatMap(_.book) Option#flatMap res0: Option[Book] = None 本が存在しないので Noneオブジェクトが
返された! 家にある本棚を本に変換してみる
// ຊ୨ͷͳ͍Ո emptyHouse.bookShelf.flatMap(_.book) Option#flatMap 家にある本棚を本に変換してみる
// ຊ୨ͷͳ͍Ո emptyHouse.bookShelf.flatMap(_.book) Option#flatMap res0: Option[Book] = None 本棚が存在しないので Noneオブジェクトが
返された! 家にある本棚を本に変換してみる
flatMap x map 家の本棚を本のタイトルに変換してみる // ຊͷஔ͔Εͨຊ୨͕͋ΔՈ houseWithFullShelf.bookShelf.flatMap(_.book).map(_.title)
家の本棚を本のタイトルに変換してみる for式 // ຊͷஔ͔Εͨຊ୨͕͋ΔՈ for { shelf <- houseWithFullShelf.bookShelf book
<- shelf.book } yield { book.title }
for式の意味を紐解く for式 houseWithFullShelf.bookShelf.flatMap { bs => bs.book.map { b =>
b.title } }
本棚にある本を条件でフィルタしてみる // ຊͷஔ͔Εͨຊ୨ fullShelf.book.filter(_.title.length > 3) Option#filter res0: Option[Book] =
Some(Book(ίοϓຊ)) 条件に合ったため Someインスタンスとして 本が返された!
// ຊͷஔ͔Εͨຊ୨ fullShelf.book.filter(_.title.length <= 3) Option#filter res0: Option[Book] = None
条件に合わないため Noneオブジェクトが 返された! 本棚にある本を条件でフィルタしてみる
// ۭͷຊ୨ emptyShelf.book.filter(_.title.length > 3) Option#filter res0: Option[Book] = None
本が存在しないので Noneオブジェクトが 返された! 本棚にある本を条件でフィルタしてみる
// ຊͷஔ͔Εͨຊ୨ fullShelf.book.foreach(b => println(b.title)) Option#foreach ίοϓຊ 本が存在するため foreachに渡した処理が 実行された!
本棚にある本のタイトルがあるときだけ 処理してみる
// ۭͷຊ୨ emptyShelf.book.foreach(b => println(b.title)) Option#foreach 本が存在しないため foreachに渡した処理が 実行されない! 本棚にある本のタイトルがあるときだけ
処理してみる
注意 今回はわかりやすいように fullShelf(常にSome[Book]を持つ) emptyShelf(常にNoneを持つ) などを用意しただけで、普通は分けない。 1つのOption型変数が状況により SomeになったりNoneになったりするのだ ということをお忘れなく!
ここからはJava! ここまでやったことをJavaで書くとどうなる か考えてみました。 アドバイスや間違いの指摘お願いします! ※必要なクラスの定義は割愛しますが、各クラスにgetterを 用意しました。
家から本棚を取り出してみる // ຊͷஔ͔Εͨຊ୨͕͋ΔՈ houseWithFullShelf.bookShelf.get Option#get相当 // ຊͷஔ͔Εͨຊ୨͕͋ΔՈ houseWithFullShelf.getBookShelf().get(); 似ている isDefined相当のisPresentもある
前述したのと同じ理由で あまり使わないはず
本棚にある本のタイトルを取り出してみる // ۭͷຊ୨ emptyShelf.getBook().map(b -> b.getTitle()).orElse(“σϑΥϧτλΠτϧ"); // ۭͷຊ୨ emptyShelf.book.map(_.title).getOrElse("σϑΥϧτλΠτϧ") Option#getOrElse相当
orElseというメソッド なおScalaのOptionにも orElseがあるが挙動は違う
Option#filter相当 // ຊͷஔ͔Εͨຊ୨ fullShelf.getBook().filter(b -> b.getTitle().length() <= 3); // ຊͷஔ͔Εͨຊ୨
fullShelf.book.filter(_.title.length <= 3) 似ている 本棚にある本を条件でフィルタしてみる
Option#foreach相当 // ຊͷஔ͔Εͨຊ୨ fullShelf.getBook().ifPresent(b -> System.out.println(b.getTitle())); // ຊͷஔ͔Εͨຊ୨ fullShelf.book.foreach(b =>
println(b.title)) 本棚にある本のタイトルがあるときだけ 処理してみる foreachはないけど ifPresentを使って 同様の処理が実現できる
Option#map相当 本棚にある本をタイトルに変換してみる // ຊͷஔ͔Εͨຊ୨ fullShelf.getBook().map(b -> b.getTitle()); // ຊͷஔ͔Εͨຊ୨ fullShelf.book.map(_.title)
似ている
家にある本棚を本に変換してみる Option#flatMap相当 // ຊͷஔ͔Εͨຊ୨͕͋ΔՈ houseWithFullShelf.getBookShelf() .flatMap(b -> b.getBook()); ほぼおなじ //
ຊͷஔ͔Εͨຊ୨͕͋ΔՈ houseWithFullShelf.bookShelf.flatMap(_.book) 似ている
パターンマッチ相当 ない?
for式相当 ない?
感想:大体似てたw
さいごに ある言語で分からなかったこと、挫折したことも、 違う言語で再挑戦すると理解できることがある 考え方を理解すれば、多少仕様やAPIが違っても すぐ馴染める 2つ以上の言語を比べると、特徴が見えてくる 言語によって出来ること・出来ないことがあるが、 それを把握することで開発する際に留意すべき 点が分かるような気がする 色々な言語に挑戦するといいことが…!