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.6k
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
0
56
シリコンバレーのチームで経験したふりかえり - 共通点とギャップ / retrospectives in silicon valley
ihcomega56
5
1.8k
「サプライチェーン攻撃」に立ち向かう!SBOMを使った脆弱性管理がもたらす品質とスピード向上
ihcomega56
2
2.2k
アプリケーション開発者目線で語る、明日から始めるDevSecOps
ihcomega56
0
130
パターンマッチングを学んで新しいJavaの世界へ!Java 18までの目玉機能をおさらいしよう / Java 18 pattern matching
ihcomega56
3
1.3k
SCAとDockerを触ってみよう!DecSecOps入門ワークショップ / SCA and Docker workshop
ihcomega56
1
230
JFrogのDevOps Platformづくりを支えるオブザーバビリティ / JFrog Observability
ihcomega56
0
430
SBOMでソフトウェアを守れ!10年後も自信を持ってリリースするために今始めるDevSecOps / DevSecOps with SBOM for yourself 10 years from now
ihcomega56
1
5.8k
Javaアプリケーションの アーティファクト管理と DevSecOps / Java artifacts management and DevSecOps
ihcomega56
0
2.4k
Other Decks in Technology
See All in Technology
ハイパーパラメータチューニングって何をしているの
toridori_dev
0
140
Terraform Stacks入門 #HashiTalks
msato
0
350
iOSチームとAndroidチームでブランチ運用が違ったので整理してます
sansantech
PRO
0
130
Why App Signing Matters for Your Android Apps - Android Bangkok Conference 2024
akexorcist
0
120
[CV勉強会@関東 ECCV2024 読み会] オンラインマッピング x トラッキング MapTracker: Tracking with Strided Memory Fusion for Consistent Vector HD Mapping (Chen+, ECCV24)
abemii
0
220
【若手エンジニア応援LT会】ソフトウェアを学んできた私がインフラエンジニアを目指した理由
kazushi_ohata
0
150
B2B SaaSから見た最近のC#/.NETの進化
sansantech
PRO
0
750
信頼性に挑む中で拡張できる・得られる1人のスキルセットとは?
ken5scal
2
530
BLADE: An Attempt to Automate Penetration Testing Using Autonomous AI Agents
bbrbbq
0
300
TypeScript、上達の瞬間
sadnessojisan
46
13k
開発生産性を上げながらビジネスも30倍成長させてきたチームの姿
kamina_zzz
2
1.7k
ノーコードデータ分析ツールで体験する時系列データ分析超入門
negi111111
0
410
Featured
See All Featured
Building an army of robots
kneath
302
43k
Git: the NoSQL Database
bkeepers
PRO
427
64k
Producing Creativity
orderedlist
PRO
341
39k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.1k
The Art of Programming - Codeland 2020
erikaheidi
52
13k
The Pragmatic Product Professional
lauravandoore
31
6.3k
Visualization
eitanlees
145
15k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
364
24k
Building Your Own Lightsaber
phodgson
103
6.1k
Music & Morning Musume
bryan
46
6.2k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
Build The Right Thing And Hit Your Dates
maggiecrowley
33
2.4k
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つ以上の言語を比べると、特徴が見えてくる 言語によって出来ること・出来ないことがあるが、 それを把握することで開発する際に留意すべき 点が分かるような気がする 色々な言語に挑戦するといいことが…!