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.7k
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
120
シリコンバレーのチームで経験したふりかえり - 共通点とギャップ / retrospectives in silicon valley
ihcomega56
5
1.9k
「サプライチェーン攻撃」に立ち向かう!SBOMを使った脆弱性管理がもたらす品質とスピード向上
ihcomega56
2
2.4k
アプリケーション開発者目線で語る、明日から始めるDevSecOps
ihcomega56
0
190
パターンマッチングを学んで新しいJavaの世界へ!Java 18までの目玉機能をおさらいしよう / Java 18 pattern matching
ihcomega56
3
1.4k
SCAとDockerを触ってみよう!DecSecOps入門ワークショップ / SCA and Docker workshop
ihcomega56
1
280
JFrogのDevOps Platformづくりを支えるオブザーバビリティ / JFrog Observability
ihcomega56
0
490
SBOMでソフトウェアを守れ!10年後も自信を持ってリリースするために今始めるDevSecOps / DevSecOps with SBOM for yourself 10 years from now
ihcomega56
1
6.3k
Javaアプリケーションの アーティファクト管理と DevSecOps / Java artifacts management and DevSecOps
ihcomega56
0
2.6k
Other Decks in Technology
See All in Technology
Strands Agents & Bedrock AgentCoreを1分でおさらい
minorun365
PRO
7
320
大規模イベントに向けた ABEMA アーキテクチャの遍歴 ~ Platform Strategy 詳細解説 ~
nagapad
0
230
LTに影響を受けてテンプレリポジトリを作った話
hol1kgmg
0
360
MCP認可の現在地と自律型エージェント対応に向けた課題 / MCP Authorization Today and Challenges to Support Autonomous Agents
yokawasa
5
2.3k
[OCI Technical Deep Dive] OracleのAI戦略(2025年8月5日開催)
oracle4engineer
PRO
1
160
生成AIによるデータサイエンスの変革
taka_aki
0
3k
九州の人に知ってもらいたいGISスポット / gis spot in kyushu 2025
sakaik
0
150
リリース2ヶ月で収益化した話
kent_code3
1
260
テストを実行してSorbetのsigを書こう!
sansantech
PRO
1
100
Instant Apps Eulogy
cyrilmottier
1
110
Foundation Model × VisionKit で実現するローカル OCR
sansantech
PRO
1
370
Rubyの国のPerlMonger
anatofuz
3
730
Featured
See All Featured
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
161
15k
A Modern Web Designer's Workflow
chriscoyier
695
190k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
283
13k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
YesSQL, Process and Tooling at Scale
rocio
173
14k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Stop Working from a Prison Cell
hatefulcrawdad
271
21k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
229
22k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
50k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
110
19k
Large-scale JavaScript Application Architecture
addyosmani
512
110k
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つ以上の言語を比べると、特徴が見えてくる 言語によって出来ること・出来ないことがあるが、 それを把握することで開発する際に留意すべき 点が分かるような気がする 色々な言語に挑戦するといいことが…!