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
ある日「Webエンジニアなら、Webサーバーは作れますよね」と言われたら? ~ 3つのJVM言...
Search
Shunsuke Tadokoro
May 20, 2021
Technology
2
530
ある日「Webエンジニアなら、Webサーバーは作れますよね」と言われたら? ~ 3つのJVM言語で作って学ぶ
技育CAMP 2021-05-20 の発表資料です。
Shunsuke Tadokoro
May 20, 2021
Tweet
Share
More Decks by Shunsuke Tadokoro
See All by Shunsuke Tadokoro
Onboarding Process for Scala Team
todokr
0
1.9k
Running Scala on AWS Lambda in a Snappy Way
todokr
7
4.5k
Scalaでつくる ちょっとしたCLIツール
todokr
0
980
新しいプログラミング言語の学び方 HTTPサーバーを作って学ぶ Java, Scala, Clojure
todokr
28
19k
わかる!Java to Clojure
todokr
6
1.8k
Scala絵文字ライブラリに Macroなどを導入してみた
todokr
0
1.4k
Clojureに入門してHTTPサーバーをつくってみた話
todokr
3
1.1k
emojiconに行ってきました
todokr
2
770
Scalaリファクタリング入門「大改造!静的ビフォー・アフター」
todokr
3
1.3k
Other Decks in Technology
See All in Technology
ローカルLLM基礎知識 / local LLM basics 2025
kishida
23
8.6k
ABEMAのCM配信を支えるスケーラブルな分散カウンタの実装
hono0130
4
1.1k
How We Built a Secure Sandbox Platform for AI
flatt_security
1
120
Digital omtanke på Internetdagarna 2025
axbom
PRO
0
120
Pandocでmd→pptx便利すぎワロタwww
meow_noisy
2
960
LINEヤフー バックエンド組織・体制の紹介
lycorptech_jp
PRO
0
850
AI エージェント活用のベストプラクティスと今後の課題
asei
2
310
AI × クラウドで シイタケの収穫時期を判定してみた
lamaglama39
1
400
Bedrock のコスト監視設計
fohte
2
220
社内外から"使ってもらえる"データ基盤を支えるアーキテクチャの秘訣/登壇資料(飯塚 大地・高橋 一貴)
hacobu
PRO
0
7.1k
クラウドネイティブ時代の 開発プロセス再設計 〜速さと品質を両立するには〜
moritamasami
0
120
重厚長大企業で、顧客価値をスケールさせるためのプロダクトづくりとプロダクト開発チームづくりの裏側 / Developers X Summit 2025
mongolyy
0
200
Featured
See All Featured
Build your cross-platform service in a week with App Engine
jlugia
234
18k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
1.8k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.1k
Statistics for Hackers
jakevdp
799
230k
Reflections from 52 weeks, 52 projects
jeffersonlam
355
21k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.4k
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
253
22k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.5k
Building Flexible Design Systems
yeseniaperezcruz
329
39k
Embracing the Ebb and Flow
colly
88
4.9k
Transcript
͋Δ ͱݴΘΕͨΒʁ ʙͭͷ+7.ݴޠͰ࡞ֶͬͯͿʙ ٕҭ$".1 !UPEPLS 8FCΤϯδχΞͳΒ 8FCαʔόʔ࡞Ε·͢ΑͶ
ଐ͞Εͯϲ݄͕ܦͬͨ͋Δͷ͜ͱ ͋Δɺَڧ͍ઌഐΤϯδχΞ͕χίχί͠ͳ͕Β͔͚͖ͯͨ͠
ଐ͞Εͯϲ݄͕ܦͬͨ͋Δͷ͜ͱ ͋Δɺَڧ͍ઌഐΤϯδχΞ͕χίχί͠ͳ͕Β͔͚͖ͯͨ͠ ాॴ͘Μ8FCΤϯδχΞͩΑͶʁ
ଐ͞Εͯϲ݄͕ܦͬͨ͋Δͷ͜ͱ ͋Δɺَڧ͍ઌഐΤϯδχΞ͕χίχί͠ͳ͕Β͔͚͖ͯͨ͠ ాॴ͘Μ8FCΤϯδχΞͩΑͶʁ ϋΠʂ
ଐ͞Εͯϲ݄͕ܦͬͨ͋Δͷ͜ͱ ͋Δɺَڧ͍ઌഐΤϯδχΞ͕χίχί͠ͳ͕Β͔͚͖ͯͨ͠ ాॴ͘Μ8FCΤϯδχΞͩΑͶʁ 8FCΤϯδχΞͬͯ͞ɺ8FCΤϯδχΞ͡ΌΜʁ ϋΠʂ
ଐ͞Εͯϲ݄͕ܦͬͨ͋Δͷ͜ͱ ͋Δɺَڧ͍ઌഐΤϯδχΞ͕χίχί͠ͳ͕Β͔͚͖ͯͨ͠ ాॴ͘Μ8FCΤϯδχΞͩΑͶʁ 8FCΤϯδχΞͬͯ͞ɺ8FCΤϯδχΞ͡ΌΜʁ 8FCαʔόʔ࡞Βͳ͍ͱʂʂʂ ϋΠʂ
ଐ͞Εͯϲ݄͕ܦͬͨ͋Δͷ͜ͱ ͋Δɺَڧ͍ઌഐΤϯδχΞ͕χίχί͠ͳ͕Β͔͚͖ͯͨ͠ ాॴ͘Μ8FCΤϯδχΞͩΑͶʁ 8FCΤϯδχΞͬͯ͞ɺ8FCΤϯδχΞ͡ΌΜʁ 8FCαʔόʔ࡞Βͳ͍ͱʂʂʂ ϋΠʂ ΞοɺϋΠ
͓͢͠Δ͜ͱ w 8FCαʔόʔͬͯԿͯ͠Δͷʁ w 4DBMB $MPKVSFʹ͍ͭͯ w 8FCαʔόʔΛ࡞Γͳ͕Βͭͷ+7.ݴޠΛֶ΅͏ w ͬ͘͟ΓΞʔΩςΫνϟ
w ֤ݴޠͰ࣮ͯ͠ΈΔ w 4PDLFUͷѻ͍ w ਖ਼نදݱ w จࣈྻͷѻ͍ w Ϧιʔεͷཧ w ฒྻॲཧ w 8FCαʔόʔΛ࡞ͬͯɺԿΛಘͨʁ
͜͏ͯ͠ 8FCαʔόʔΛ࡞Δʑ͕ ࢝·ͬͨ
ͱ͍͑
8FCαʔόʔͬͯԿͯ͠Δͷʁ
8FCαʔόʔ͕͍ͬͯΔ͜ͱ w ΫϥΠΞϯτ͔ΒͷଓΛͪड͚Δ w ΫϥΠΞϯτ͔ΒૹΒΕ͖ͯͨ)551ϦΫΤετΛύʔε͢Δ w ϦΫΤετʹج͍ͮͯ)551ϨεϙϯεΛੜ͢Δ w ΫϥΠΞϯτʹϨεϙϯεΛฦ͢
)551ͷن֨Λཧղ͠Α͏ ௐΛ͍ͯ͠Δͱɺ·َͨͯ͠ڧ͍ઌഐΤϯδχΞ͕ χίχί͠ͳ͕Β͔͚͖ͯͨ͠
)551ͷن֨Λཧղ͠Α͏ ௐΛ͍ͯ͠Δͱɺ·َͨͯ͠ڧ͍ઌഐΤϯδχΞ͕ χίχί͠ͳ͕Β͔͚͖ͯͨ͠ ʢʮ)551Θ͔Γ͘͢ʯͰݕࡧͱʣ
)551ͷن֨Λཧղ͠Α͏ ௐΛ͍ͯ͠Δͱɺ·َͨͯ͠ڧ͍ઌഐΤϯδχΞ͕ χίχί͠ͳ͕Β͔͚͖ͯͨ͠ 8FCΤϯδχΞͳΒҰ࣍ใʹͨΒͳ͍ͱʂ ʢʮ)551Θ͔Γ͘͢ʯͰݕࡧͱʣ
)551ͷن֨Λཧղ͠Α͏ ௐΛ͍ͯ͠Δͱɺ·َͨͯ͠ڧ͍ઌഐΤϯδχΞ͕ χίχί͠ͳ͕Β͔͚͖ͯͨ͠ 8FCΤϯδχΞͳΒҰ࣍ใʹͨΒͳ͍ͱʂ 3'$Λಡ͏ͥʂʂʂ ʢʮ)551Θ͔Γ͘͢ʯͰݕࡧͱʣ
)551ͷن֨Λཧղ͠Α͏ ௐΛ͍ͯ͠Δͱɺ·َͨͯ͠ڧ͍ઌഐΤϯδχΞ͕ χίχί͠ͳ͕Β͔͚͖ͯͨ͠ 8FCΤϯδχΞͳΒҰ࣍ใʹͨΒͳ͍ͱʂ 3'$Λಡ͏ͥʂʂʂ ʢʮ)551Θ͔Γ͘͢ʯͰݕࡧͱʣ ΞοɺϋΠ
)551ͷن֨Λཧղ͠Α͏ ௐΛ͍ͯ͠Δͱɺ·َͨͯ͠ڧ͍ઌഐΤϯδχΞ͕ χίχί͠ͳ͕Β͔͚͖ͯͨ͠ 8FCΤϯδχΞͳΒҰ࣍ใʹͨΒͳ͍ͱʂ 3'$Λಡ͏ͥʂʂʂ ʢʮ)551Θ͔Γ͘͢ʯͰݕࡧͱʣ ΞοɺϋΠ ʢ3'$JTԿʣ
3'$ʢ3FRVFTU'PS$PNNFOUTʣ w *&5'ʹΑΔٕज़༷ͷอଘɺެ։ܗࣜ w ϓϩτίϧϑΝΠϧϑΥʔϚοτͳͲ͕த৺ w )5513'$d
IUUQTUPPMTJFUGPSHIUNMSGD
IUUQIUUQXHPSH
؆қͳ࣮ͳΒඦߦఔ👍
1ZUIPOͷ4JNQMF)5514FSWFS w 1ZUIPOͷ4JNQMF)5514FSWFSͷڍಈΛࢀߟʹ͢Δͷྑ͍ w ܥ w ܥ $ python -m
SimpleHTTPServer $ python -m http.server
w 4DBMB w +BWB w 1ZUIPO w $MPKVSF w $PNNPO-JTQ
w &MJYJS w %BSU
w 4DBMB w +BWB w 1ZUIPO w $MPKVSF w $PNNPO-JTQ
w &MJYJS w %BSU
8FCαʔόʔΛ࡞Γͳ͕Β ͭͷ+7.ݴޠΛֶ΅͏ʂ
4DBMB$MPKVSF
4DBMB
4DBMB w +BWBͱͷ૬ޓӡ༻ੑ w γʔϜϨεͳݺͼग़͠ɺ+BWBඪ४ϥΠϒϥϦͷ࠶ར༻ w ؆ܿੑ w লུՄೳͳߏจɺܕਪɺڧྗͳඪ४ϥΠϒϥϦ w
நͷߴ͍ίʔυɺ৽੍͍͠ޚߏจΛఆٛͰ͖Δදݱྗ w 8IBUͷڧௐɺ)PXͷӅณ w ੩తܕ͚ w ݕূՄೳੑɺϦϑΝΫλͷ͢͠͞ɺυΩϡϝϯτੑ
IUUQTXXXMJIBPZJDPNQPTU'SPN'JSTU1SJODJQMFT8IZ4DBMBIUNM
"$PNQJMFE-BOHVBHFUIBUGFFMT%ZOBNJD requests.post( "https://api.github.com/repos/lihaoyi/test/issues", data = ujson.Obj("title" -> "hello"), headers =
Map("Authorization" -> s"token $token") )
4DBMBܕͷදݱྗ // `@`͔Β࢝·ͬͯ3จࣈҎ্16จࣈҎɺ@admin@Adminڐ༰͠ͳ͍ type UserIdRule = StartsWith["@"] And MinSize[3] And
MaxSize[16] And Not[MatchesRegex["(?i)@admin"]] val userId1: String Refined UserIdRule = "@todokr" // ҎԼίϯύΠϧΤϥʔ val userId2: String Refined UserIdRule = "@admin" val userId3: String Refined UserIdRule = "todokr" val userId4: String Refined UserIdRule = "@uryyyyyyyyyyyyyy"
IUUQTFOHJOFFSJOHWJTJPOBMJODCMPHTDBMBSFpOFEOFXUZQF
$MPKVSF
$MPKVSF w -JTQ w จ๏͕গͳ͍ɺσʔλͱͯ͠ͷίʔυ w ؔܕϓϩάϥϛϯάͷͨΊͷݴޠ w ୈҰڃؔɺΠϛϡʔλϒϧͳσʔλߏɺ࠶ؼతͳϧʔϓ w
+BWBͱͷ૬ޓӡ༻ੑ w ฒߦॲཧͷͨΊʹઃܭ w 3&1-Λ׆͔ͨ͠ΠϯλϥΫςΟϒΠϯΫϦϝϯλϧͳ։ൃ
ϙʔϧɾάϨΞϜ 7JBXFCۀऀ :$PNCJOBUPSઃऀ IUUQTVQMPBEXJLJNFEJBPSHXJLJQFEJB DPNNPOTFF1BVMHSBIBN@YKQH
-JTQͰྑ͍ϓϩάϥϜ͕ॻ͚ΔͳΒɺ͏͖ͳΜͩɻ ͦ͏Ͱͳ͍ͳΒ͍͍ͬͨԿͷʹཱͭ ϙʔϧɾάϨΞϜ 7JBXFCۀऀ :$PNCJOBUPSઃऀ IUUQTVQMPBEXJLJNFEJBPSHXJLJQFEJB DPNNPOTFF1BVMHSBIBN@YKQH
ී௨ͷౕΒͷ্Λߦ͚ɻ -JTQͰྑ͍ϓϩάϥϜ͕ॻ͚ΔͳΒɺ͏͖ͳΜͩɻ ͦ͏Ͱͳ͍ͳΒ͍͍ͬͨԿͷʹཱͭ ϙʔϧɾάϨΞϜ 7JBXFCۀऀ :$PNCJOBUPSઃऀ IUUQTVQMPBEXJLJNFEJBPSHXJLJQFEJB DPNNPOTFF1BVMHSBIBN@YKQH
ී௨ͷౕΒͷ্Λߦ͚ɻ -JTQͰྑ͍ϓϩάϥϜ͕ॻ͚ΔͳΒɺ͏͖ͳΜͩɻ ͦ͏Ͱͳ͍ͳΒ͍͍ͬͨԿͷʹཱͭ :BIPPʹച٫ ϙʔϧɾάϨΞϜ 7JBXFCۀऀ :$PNCJOBUPSઃऀ IUUQTVQMPBEXJLJNFEJBPSHXJLJQFEJB DPNNPOTFF1BVMHSBIBN@YKQH
ී௨ͷౕΒͷ্Λߦ͚ɻ -JTQͰྑ͍ϓϩάϥϜ͕ॻ͚ΔͳΒɺ͏͖ͳΜͩɻ ͦ͏Ͱͳ͍ͳΒ͍͍ͬͨԿͷʹཱͭ Θͨ͠ ී௨ͷϓϩάϥϚ -JTQͰΣϒαʔϏεΛͭ͘Δͱ :BIPPʹԯԁͰങͬͯΒ͑Δʂʂʂ :BIPPʹച٫ ϙʔϧɾάϨΞϜ 7JBXFCۀऀ
:$PNCJOBUPSઃऀ IUUQTVQMPBEXJLJNFEJBPSHXJLJQFEJB DPNNPOTFF1BVMHSBIBN@YKQH
ίϯηϓτ͕໘ന͍ w ঢ়ଶʹ͍ͭͯͷߟ͑ํɺ*EFOUJUZ 4UBUF 7BMVFͷ w γϯϓϧ͞ʹ͍ͭͯ ͍Ζ͍Ζܹత
IUUQTKBQBODMPKVSJBOTHJUIVCJPDMPKVSFTJUFKBBCPVUSBUJPOBMF
IUUQTKBQBODMPKVSJBOTHJUIVCJPDMPKVSFTJUFKBBCPVUSBUJPOBMF
IUUQTFFETJODPNKBTJNQMJDJUZNBUUFST
IUUQCPYPGQBQFSTIBUFOBCMPHDPNFOUSZTJNQMF@NBEF@FBTZ
-JTQͷγϯλοΫε ׅހͷ࢝·Γ͔ΒऴΘΓ·Ͱ͕୯Ґ (ԿΒ͔ͷॲཧ ॲཧͷରͳͲ…)
$MPKVSFΧοίͷछྨ͕ଟ͘ɺಡΈ͍͢ ͨͱ͑ؔͷҾ $PNNPO-JTQ 4DIFNF $MPKVSF (defun square (x) (* x
x)) (define (square x) (* x x)) (defn square [x] (* x x))
😌 େৎ
😌 ৴͍ͯͩ͘͡͞
جຊจ๏ͰΥʔϛϯάΞοϓ
࢛ଇԋࢉ
࢛ଇԋࢉ 12 + 40 10 - 1 2 * 3
5 / 2 +BWB 4DBMB
࢛ଇԋࢉ 12 + 40 10 - 1 2 * 3
5 / 2 +BWB 4DBMB (+ 12 40) (- 10 1) (* 2 3) (/ 5 2) ; -> 5/2 Λѻ͏Ratioܕ $MPKVSF
มએݴ
มએݴ int x = 10; +BWB
มએݴ int x = 10; +BWB val x = 10
val x: Int = 10 4DBMB
มએݴ int x = 10; +BWB val x = 10
val x: Int = 10 4DBMB (def x 10) (let [y 10] (+ y 3)) ; yletͷׅހ͚ͩͰࢀরͰ͖Δ $MPKVSF
ϝιουɾؔએݴ
ϝιουɾؔએݴ public int f(int x) { return x + 1;
} +BWB
ϝιουɾؔએݴ public int f(int x) { return x + 1;
} +BWB def f(x: Int) = x + 1 4DBMB
ϝιουɾؔએݴ public int f(int x) { return x + 1;
} +BWB (defn f [x] (+ x 1)) $MPKVSF def f(x: Int) = x + 1 4DBMB
👍
ࠓճ༻ҙ࣮ͨ͠ w ىಈ͠ɺMPDBMIPTUͷಛఆͷϙʔτͰ)551ϦΫΤετΛͪड͚Δ w ରԠ͢Δ)551ϦΫΤετϝιου(&5ͷΈ ͦΕҎ֎ͷϝιου(&5ͱΈͳ͢ w QVCMJDσΟϨΫτϦΑΓ্ͷ֊ͷϦΫΤετʹ 'PSCJEEFOΛฦ͢ w
Ϧιʔεͷ.*.&֎෦ϑΝΠϧͰઃఆͰ͖Δ w ϦΫΤετΛϒϩοΫ͠ͳ͍ʢϚϧνεϨουʣ w ,FFQ"MJWF͠ͳ͍ɻίωΫγϣϯDMPTF͢Δ w )551$BDIF͠ͳ͍ɻฦ͞ͳ͍
IUUQTHJUIVCDPNUPEPLSTJNQMFIUUQTFSWFS
ͭ͘Γʹ͍ͭͯͬ͘͟Γͱ ᵓᴷᴷ.JNF%FUFDUPSKBWB ᵓᴷᴷ3FRVFTUKBWB ᵓᴷᴷ3FRVFTU)BOEMFSKBWB ᵓᴷᴷ3FRVFTU1BSTFSKBWB ᵓᴷᴷ3FTQPOTFKBWB ᵓᴷᴷ4JNQMF+BWB)UUQ4FSWFSKBWB ᵋᴷᴷ8PSLFS5ISFBEKBWB 8FCαʔόʔΞϓϦέʔγϣϯ 3FRVFTU
*OQVU4USFBN 3FTQPOTF 0VUQVU4USFBN )551ϦΫΤετͷύʔε ϦΫΤετʹԠͨ͡ Ϩεϙϯεͷੜ )551Ϩεϙϯεͷฦ٫
ͭ͘Γʹ͍ͭͯͬ͘͟Γͱ ᵓᴷᴷ.JNF%FUFDUPSKBWB ᵓᴷᴷ3FRVFTUKBWB ᵓᴷᴷ3FRVFTU)BOEMFSKBWB ᵓᴷᴷ3FRVFTU1BSTFSKBWB ᵓᴷᴷ3FTQPOTFKBWB ᵓᴷᴷ4JNQMF+BWB)UUQ4FSWFSKBWB ᵋᴷᴷ8PSLFS5ISFBEKBWB 8FCαʔόʔΞϓϦέʔγϣϯ 3FRVFTU
*OQVU4USFBN 3FTQPOTF 0VUQVU4USFBN )551ϦΫΤετͷύʔε ϦΫΤετʹԠͨ͡ Ϩεϙϯεͷੜ )551Ϩεϙϯεͷฦ٫
ͭ͘Γʹ͍ͭͯͬ͘͟Γͱ ᵓᴷᴷ.JNF%FUFDUPSKBWB ᵓᴷᴷ3FRVFTUKBWB ᵓᴷᴷ3FRVFTU)BOEMFSKBWB ᵓᴷᴷ3FRVFTU1BSTFSKBWB ᵓᴷᴷ3FTQPOTFKBWB ᵓᴷᴷ4JNQMF+BWB)UUQ4FSWFSKBWB ᵋᴷᴷ8PSLFS5ISFBEKBWB 8FCαʔόʔΞϓϦέʔγϣϯ 3FRVFTU
*OQVU4USFBN 3FTQPOTF 0VUQVU4USFBN )551ϦΫΤετͷύʔε ϦΫΤετʹԠͨ͡ Ϩεϙϯεͷੜ )551Ϩεϙϯεͷฦ٫
ͭ͘Γʹ͍ͭͯͬ͘͟Γͱ ᵓᴷᴷ.JNF%FUFDUPSKBWB ᵓᴷᴷ3FRVFTUKBWB ᵓᴷᴷ3FRVFTU)BOEMFSKBWB ᵓᴷᴷ3FRVFTU1BSTFSKBWB ᵓᴷᴷ3FTQPOTFKBWB ᵓᴷᴷ4JNQMF+BWB)UUQ4FSWFSKBWB ᵋᴷᴷ8PSLFS5ISFBEKBWB 8FCαʔόʔΞϓϦέʔγϣϯ 3FRVFTU
*OQVU4USFBN 3FTQPOTF 0VUQVU4USFBN )551ϦΫΤετͷύʔε ϦΫΤετʹԠͨ͡ Ϩεϙϯεͷੜ )551Ϩεϙϯεͷฦ٫
ͭ͘Γʹ͍ͭͯͬ͘͟Γͱ ᵓᴷᴷ.JNF%FUFDUPSKBWB ᵓᴷᴷ3FRVFTUKBWB ᵓᴷᴷ3FRVFTU)BOEMFSKBWB ᵓᴷᴷ3FRVFTU1BSTFSKBWB ᵓᴷᴷ3FTQPOTFKBWB ᵓᴷᴷ4JNQMF+BWB)UUQ4FSWFSKBWB ᵋᴷᴷ8PSLFS5ISFBEKBWB 8FCαʔόʔΞϓϦέʔγϣϯ 3FRVFTU
*OQVU4USFBN 3FTQPOTF 0VUQVU4USFBN )551ϦΫΤετͷύʔε ϦΫΤετʹԠͨ͡ Ϩεϙϯεͷੜ )551Ϩεϙϯεͷฦ٫
֤ݴޠͰͬͯΈΔ w 4PDLFUͷѻ͍ w ਖ਼نදݱ w จࣈྻͷѻ͍ w Ϧιʔεͷ։์ w
ฒߦॲཧ
4PDLFUͷѻ͍
4PDLFU
4PDLFU w ௨৴ʹ͓͚ΔΤϯυϙΠϯτΛදݱͨ͠σʔλϞσϧ ֤ΤϯυϙΠϯτΛࣝผ͢Δ̎ͭͷɺ ͢ͳΘͪ*1ΞυϨεͱϙʔτ൪߸ɺ ଟ͘ͷ߹ιέοτ TPDLFU ͱݺΕΔɻ ʮ6/*9ωοτϫʔΫϓϩάϥϛϯάʯIUUQTXXXTFTIPQDPNQSPEVDUEFUBJM
4PDLFU௨৴ͷࣜਤ ΫϥΠΞϯτ αʔόʔ
4PDLFU௨৴ͷࣜਤ ΫϥΠΞϯτ αʔόʔ αʔόʔιέοτ
4PDLFU௨৴ͷࣜਤ ΫϥΠΞϯτ αʔόʔ αʔόʔιέοτ ΫϥΠΞϯτιέοτ
4PDLFU௨৴ͷࣜਤ ΫϥΠΞϯτ αʔόʔ αʔόʔιέοτ ΫϥΠΞϯτιέοτ ଓཁٻ
4PDLFU௨৴ͷࣜਤ ΫϥΠΞϯτ αʔόʔ αʔόʔιέοτ ΫϥΠΞϯτιέοτ ଓ
4PDLFU௨৴ͷࣜਤ ΫϥΠΞϯτ αʔόʔ αʔόʔιέοτ ΫϥΠΞϯτιέοτ 😂 😂
4PDLFUͷѻ͍ // αʔόʔιέοτͷੜ ServerSocket serverSocket = new ServerSocket(8080); while (true)
{ // ଓΛͪड͚Δɻଓ͞ΕΔ·ͰϒϩοΫɻ Socket socket = serverSocket.accept(); InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); ... } ιέοτͷੜͱଓͷͪड͚
4PDLFUͷѻ͍ // αʔόʔιέοτͷੜ val serverSocket = new ServerSocket(8080) while (true)
{ // ଓΛͪड͚Δɻଓ͞ΕΔ·ͰϒϩοΫ val socket = serverSocket.accept val in = s.getInputStream val out = s.getOutputStream ... } ιέοτͷੜͱଓͷͪड͚
4PDLFUͷѻ͍ (let [server-socket (new ServerSocket 8080)] (while true (let [socket
(.accept server-socket) in (.getInputStream socket) out (.getOutputStream socket)] ...))) ιέοτͷੜͱଓͷͪड͚
4PDLFUͷѻ͍ʹֶ͍ͭͯΜͩ͜ͱ w 4FSWFS4PDLFUΦϒδΣΫτΛੜ͠ɺ ΫϥΠΞϯτ͔ΒͷଓΛBDDFQUͰͪड͚Δ w 4PDLFUΦϒδΣΫτʢΫϥΠΞϯτιέοτʣ͔Β *O0VUQVU4USFBN͕औಘͰ͖Δ w *OQVU4USFBN͔Β)551ϦΫΤετΛ3FBE͠ɺ 0VUQVU4USFBNʹ)551ϨεϙϯεΛ8SJUF͢Δ
ਖ਼نදݱ
ਖ਼نදݱ w 4PDLFUͷ*OQVU4USFBNΛҰߦಡΉ ˠSFRVFTUMJOF w ֤ཁૉΛநग़͍ͨ͠
ਖ਼نදݱ w 4PDLFUͷ*OQVU4USFBNΛҰߦಡΉ ˠSFRVFTUMJOF w ֤ཁૉΛநग़͍ͨ͠
ਖ਼نදݱ w 4PDLFUͷ*OQVU4USFBNΛҰߦಡΉ ˠSFRVFTUMJOF w ֤ཁૉΛநग़͍ͨ͠
໊લ͖άϧʔϓ
໊લ͖άϧʔϓ w ਖ਼نදݱͷάϧʔϓʹ໊લΛ͚Δ͜ͱ͕Ͱ͖Δ w άϧʔϓͷॱং͕มΘͬͨͱͯ͠औΓग़͢ॲཧͦͷ··Ͱྑ͍ import java.util.regex.*; String regex =
"(?<year>\\d+)/(?<month>\\d+)/(?<day>\\d+)"; Pattern p = Pattern.compile(regex); Matcher m = p.matcher("2017/11/18"); if (m.find()) { System.out.println(m.group("year")); // 2017 System.out.println(m.group("month")); // 11 System.out.println(m.group("day")); // 18 }
public static Pattern requestLinePattern = Pattern.compile("(?<method>.*) (?<path>.*?) (?<version>.*?)"); public Request
fromInputStream(InputStream in){ BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String requestLine = reader.readLine(); Matcher matcher = requestLinePattern.matcher(requestLine); if (!matcher.find()) return null; String method = matcher.group("method"); String targetPath = matcher.group("path"); String httpVersion = matcher.group("version"); return new Request(method, targetPath, httpVersion); } ໊લ͖άϧʔϓ ϦΫΤετϥΠϯͷ֤ཁૉʹ໊લΛ͚ͯநग़
ύλʔϯϚον S
ύλʔϯϚον w +BWBͷTXJUDIจʹࣅ͍ͯΔ͕ɺΑΓॊೈͰڧྗ w ʹҰக͢Δ͔͚ͩͰͳ͘ɺܕߏͰذͤ͞Δ͜ͱ͕Ͱ͖Δ 0 match { case 0
=> "Zero" // "Zero" case _ => "Other" } List(1, 2, 3) match { case List(_, x, _) => x // 2 case _ => -1 } 1 match { x: Int => s"$xInt" // 1Int x: String => s"$xString" x => s"$x???" }
ύλʔϯϚον w ਖ਼نදݱΦϒδΣΫτʹରͯ͠Ϛονͤ͞Δ͜ͱ͕Ͱ͖Δ val Pattern = "(.+)/(.+)/(.+)".r //.rͰregexܕ “2021/05/20" match
{ case Pattern(y, m, d) => s"${y}${m}݄${d}" case _ => "???" }
ύλʔϯϚον val Pattern = "(.+) (.+) (.+)".r requestLine match {
case Pattern(method, path, version) => Some(Request(method, path, version)) case _ => None } 3FRVFTU1BSTFSTDBMBʢൈਮҰ෦վมʣ
0QUJPOܕ requestLine match { case pattern(method, path, version) => Some(Request(method,
path, version)) case _ => None } w +BWBͰ͍͏0QUJPOBMʢΈ͍ͨͳͷʣ w )BTLFMMͰ͍͏.BZCF w 4PNFͱ/POF͔ΒͳΔܕʢతσʔλܕʣ w ͕͋Δ͔ͳ͍͔͔Βͳ͍ঢ়ଶΛද͢ w ͕ଘࡏ͢Δ͔ͷνΣοΫΛڧ੍Ͱ͖Δ
SFpOE
SFpOE w ਖ਼نදݱʹϚονͨ͠จࣈྻΛऔಘ w ҾʹάϧʔϓԽͨ͠ਖ਼نදݱΦϒδΣΫτΛ͢ͱɺ ઌ಄ʹϚονͨ͠จࣈྻશମɺҎ߱ʹΩϟϓνϟ͞ΕͨจࣈྻͷϕΫλʔ ;; #"" java.util.regex.PatternͷϦςϥϧ (re-find
#"(.+)/(.+)/(.+)" "2017/11/18") ;; => ["2017/11/18" "2017" "11" "18"] ;; restͰઌ಄Ҏ֎ͷཁૉΛऔಘ (rest (re-find #"(.+)/(.+)/(.+)" "2017/11/18")) ;; => ("2017" "11" "18")
[JQNBQ w ڧྗͳίϨΫγϣϯϥΠϒϥϦ$MPKVSFͷಛ w [JQNBQͭͷίϨΫγϣϯ͔Β.BQΛ࡞Δ w $MPKVSFͰΫϥεΑΓ.BQΛΉ (zipmap [:a :b
:c] [1 2 3]) ;; => {:a 1, :b 2, :c 3}
SFpOE [JQNBQ (let [line "GET / HTTP/1.1"] (zipmap [:method :path
:version] (rest (re-find #"(.+) (.+) (.+)" line)))) ;; => {:method "GET", :path "/", :version "HTTP/1.1"} ϦΫΤετϥΠϯͷ֤ཁૉΛ.BQʹม
SFpOE [JQNBQ <NFUIPEQBUIWFSTJPO> <(&5)551> (let [line "GET / HTTP/1.1"] (zipmap
[:method :path :version] (rest (re-find #"(.+) (.+) (.+)" line)))) ;; => {:method "GET", :path "/", :version "HTTP/1.1"} ϦΫΤετϥΠϯͷ֤ཁૉΛ.BQʹม
SFpOE [JQNBQ <NFUIPEQBUIWFSTJPO> <(&5)551> (let [line "GET / HTTP/1.1"] (zipmap
[:method :path :version] (rest (re-find #"(.+) (.+) (.+)" line)))) ;; => {:method "GET", :path "/", :version "HTTP/1.1"} ϦΫΤετϥΠϯͷ֤ཁૉΛ.BQʹม
SFpOE [JQNBQ <NFUIPEQBUIWFSTJPO> <(&5)551> (let [line "GET / HTTP/1.1"] (zipmap
[:method :path :version] (rest (re-find #"(.+) (.+) (.+)" line)))) ;; => {:method "GET", :path "/", :version "HTTP/1.1"} ϦΫΤετϥΠϯͷ֤ཁૉΛ.BQʹม
ਖ਼نදݱʹֶ͍ͭͯΜͩ͜ͱ
ਖ਼نදݱʹֶ͍ͭͯΜͩ͜ͱ ໊લ͖άϧʔϓ
ਖ਼نදݱʹֶ͍ͭͯΜͩ͜ͱ ໊લ͖άϧʔϓ ఴࣈͰΞΫηε͢ΔΑΓ҆৺
ਖ਼نදݱʹֶ͍ͭͯΜͩ͜ͱ ໊લ͖άϧʔϓ ύλʔϯϚον S ఴࣈͰΞΫηε͢ΔΑΓ҆৺
ਖ਼نදݱʹֶ͍ͭͯΜͩ͜ͱ ໊લ͖άϧʔϓ ύλʔϯϚον S ఴࣈͰΞΫηε͢ΔΑΓ҆৺ ߏͷղʹ͑Δ
ਖ਼نදݱʹֶ͍ͭͯΜͩ͜ͱ ໊લ͖άϧʔϓ ύλʔϯϚον S SFpOE ఴࣈͰΞΫηε͢ΔΑΓ҆৺ ߏͷղʹ͑Δ
ਖ਼نදݱʹֶ͍ͭͯΜͩ͜ͱ ໊લ͖άϧʔϓ ύλʔϯϚον S SFpOE ఴࣈͰΞΫηε͢ΔΑΓ҆৺ ߏͷղʹ͑Δ ݁ՌίϨΫγϣϯɺίϨΫγϣϯૢ࡞ͱΈ߹Θͤͯ
จࣈྻͷѻ͍
จࣈྻ݁߹ w ϨεϙϯεʢΦϒδΣΫτϚοϓʣ͔Β )551ϨεϙϯεϔομΛΈཱ͍ͯͨ public class Response { public final
Status status; public final String contentType; public final int contentLength; public final byte[] body; }
4USJOH#VJMEFS
4USJOH#VJMEFS String response = "HTTP/1.1 " + status.statusCode + CRLF
+ "Server: SimpleJavaHttpServer" + CRLF + "Content-Type: " + contentType + CRLF + "Content-Length: " + String.valueOf(contentLength) + CRLF + "Connection: Close" + CRLF + CRLF; 3FTQPOTFΦϒδΣΫτΛ)551Ϩεϙϯεม
4USJOH*OUFSQPMBUJPO 5SJQMF2VPUF
4USJOH*OUFSQPMBUJPO w จࣈྻϦςϥϧͷલʹTΛ͚ΔͱɺมΛల։Ͱ͖Δ val price = 1000 s"Price is $price"
// => Price is 1000
5SJQMF2VPUF "Hello triple quote!\nHello stripMargin!" """Hello triple quote! Hello stripMargin!"""
"""|Hello triple quote! |Hello stripMargin!""".stripMargin w վߦΛؚΉจࣈྻΛຒΊࠐΉʹɺΛ͏ w ΠϯσϯτΛଗ͑ΔʹΠϯσϯτจࣈ c ͱTUSJQ.BSHJOΛ͏
4USJOH*OUFSQPMBUJPOͱ5SJQMF2VPUF val response = s"""HTTP/1.1 ${status.value} |Date: ${rfc1123Formatter.format(now)} |Server: SimpleScalaHttpServer
|Content-Type: $contentType |Content-Length: ${body.length.toString} |Connection: Close | |""".stripMargin 3FTQPOTFΦϒδΣΫτΛ)551Ϩεϙϯεม
TUS
w $MPKVSFͰจࣈྻͷ݁߹ Ͱͳ͘TUS w ՄมҾɺ4ࣜͳΒͰ TUS (+ "hoge" "fuga") ClassCastException
java.lang.String cannot be cast to java.lang.Number clojure.lang.Numbers.add (Numbers.java:128) (str "hoge" "fuga" "piyo") // => hogefugapiyo
TUS (let [header (str "HTTP/1.1" SP status SP reason-phrase CRLF
"Content-Length:" (count body) CRLF "Content-Type:" content-type CRLF "Connection: Close" CRLF CRLF)] ...) 3FTQPOTFΦϒδΣΫτΛ)551Ϩεϙϯεม
จࣈྻ݁߹ʹֶ͍ͭͯΜͩ͜ͱ
จࣈྻ݁߹ʹֶ͍ͭͯΜͩ͜ͱ 4USJOH#VJMEFS
จࣈྻ݁߹ʹֶ͍ͭͯΜͩ͜ͱ 4USJOH#VJMEFS ࠷దԽʹࣗ৴͕ͳ͚ΕKBWBQD
จࣈྻ݁߹ʹֶ͍ͭͯΜͩ͜ͱ 4USJOH#VJMEFS 4USJOH*OUFSQPMBUJPO 5SJQMF2VPUF ࠷దԽʹࣗ৴͕ͳ͚ΕKBWBQD
จࣈྻ݁߹ʹֶ͍ͭͯΜͩ͜ͱ 4USJOH#VJMEFS 4USJOH*OUFSQPMBUJPO 5SJQMF2VPUF ࠷దԽʹࣗ৴͕ͳ͚ΕKBWBQD ͪΐͬͱͨ͠ςϯϓϨʔτΤϯδϯΈ͍ͨʹ͑Δ
จࣈྻ݁߹ʹֶ͍ͭͯΜͩ͜ͱ 4USJOH#VJMEFS 4USJOH*OUFSQPMBUJPO 5SJQMF2VPUF TUS ࠷దԽʹࣗ৴͕ͳ͚ΕKBWBQD ͪΐͬͱͨ͠ςϯϓϨʔτΤϯδϯΈ͍ͨʹ͑Δ
จࣈྻ݁߹ʹֶ͍ͭͯΜͩ͜ͱ 4USJOH#VJMEFS 4USJOH*OUFSQPMBUJPO 5SJQMF2VPUF TUS ࠷దԽʹࣗ৴͕ͳ͚ΕKBWBQD ͪΐͬͱͨ͠ςϯϓϨʔτΤϯδϯΈ͍ͨʹ͑Δ 4ࣜͳΒͰ
Ϧιʔεͷཧ
Ϧιʔεͷཧ w ετϦʔϜ%#ίωΫγϣϯɺιέοτ͍ऴΘͬͨΒDMPTF w ΕΔͱϝϞϦϦʔΫͷݪҼʹͳΔ͜ͱ͕͋Δ w खͰDMPTFॻ͖ͨ͘ͳ͍ʂ😫
5SZXJUI3FTPVSDFT
5SZXJUI3FTPVSDFT try (InputStream in = new FileInputStream(file)) { // Կ͔ϦιʔεΛѻ͏ॲཧ
} // try۟Λൈ͚ͨΒclose w USZ۟Λൈ͚ͨΒࣗಈͰDMPTF w ରKBWBJP$MPTFBCMF KBWBMBOH"VUP$MPTFBCMFͷ࣮Ϋϥε
-PBO1BUUFSO
-PBO1BUUFSO w ʮआΓͨΒฦ͢ʯΛ࣮֬ʹߦ͏ͨΊͷΠσΟΦϜ w ͔͋ͨݴޠ੍͕࣋ͭޚߏͷΑ͏ͳϝιουΛɺ ϓϩάϥϚ͕؆୯ʹఆٛͰ͖Δͷ4DBMBͷΑ͍ͱ͜Ζ val reader = new
BufferedReader(...) using(reader) { r => // readerΛͬͨԿ͔ͷॲཧ } // ϒϩοΫΛൈ͚ͨΒreaderclose͞Ε͍ͯΔ ˞4DBMB͔Βඪ४ϥΠϒϥϦʹˢͱ΄΅ಉͷTDBMBVUJM6TJOH͕Ճ͞Ε·͕ͨ͠ɺ ΠϝʔδΛ௫ΉͨΊʹࣗͰ࣮ͯ͠Έ·͢
-PBO1BUUFSOͷ࣮ def using[A, R <: Closeable](resource: R)(f: R => A):
A = { try { f(resource) } finally { resource.close() } }
-PBO1BUUFSOͷ࣮ def using[A, R <: Closeable](resource: R)(f: R => A):
A = { try { f(resource) } finally { resource.close() } } ܕม3$MPTFBCMF͔ͦͷαϒλΠϓɻDMPTFϝιουΛ࣋ͭ͜ͱΛอূɻ
-PBO1BUUFSOͷ࣮ def using[A, R <: Closeable](resource: R)(f: R => A):
A = { try { f(resource) } finally { resource.close() } } 3ܕͷԿ͔Λड͚औΓɺԿΒ͔ͷܕ"Λฦؔ͢ΛҾʹͱΔ
-PBO1BUUFSOͷ࣮ def using[A, R <: Closeable](resource: R)(f: R => A):
A = { try { f(resource) } finally { resource.close() } } Ϧιʔεʹରͯؔ͠Λద༻
-PBO1BUUFSOͷ࣮ def using[A, R <: Closeable](resource: R)(f: R => A):
A = { try { f(resource) } finally { resource.close() } } ࠷ޙʹDMPTF
-PBO1BUUFSO using(socket) { s => val in = s.getInputStream val
out = s.getOutputStream val request = parser.fromInputStream(in) val response = request.map(handleRequest) response.foreach(_.writeTo(out)) } VTJOHϒϩοΫΛൈ͚ͨΒɺTPDLFUΛDMPTF͢Δ
XJUIPQFO
w -PBO1BUUFSOʹࣅͨXJUIPQFOͱ͍͏ϚΫϩ w MFUͱಉ͡Α͏ͳײ͡Ͱ͏ XJUIPQFO (with-open [f (io/file "test.txt")] ...)
XJUIPQFO (with-open [s socket] (-> (request-parser/from-input-stream (.getInputStream s)) (request-handler/handle-request) (response-writer/write
(.getOutputStream s)))) XJUIPQFOΛൈ͚ͨΒɺTPDLFUΛDMPTF͢Δ
Ϧιʔεͷཧʹֶ͍ͭͯΜͩ͜ͱ
Ϧιʔεͷཧʹֶ͍ͭͯΜͩ͜ͱ 5SZXJUI3FTPVSDFT
Ϧιʔεͷཧʹֶ͍ͭͯΜͩ͜ͱ 5SZXJUI3FTPVSDFT USZ۟Λൈ͚Δ࣌ʹDMPTF
Ϧιʔεͷཧʹֶ͍ͭͯΜͩ͜ͱ 5SZXJUI3FTPVSDFT -PBO1BUUFSO USZ۟Λൈ͚Δ࣌ʹDMPTF
Ϧιʔεͷཧʹֶ͍ͭͯΜͩ͜ͱ 5SZXJUI3FTPVSDFT -PBO1BUUFSO USZ۟Λൈ͚Δ࣌ʹDMPTF ͕ؔͰ͋Δ͜ͱΛ׆͔͠ɺ੍ޚߏจͷΑ͏ʹݟͤΔ
Ϧιʔεͷཧʹֶ͍ͭͯΜͩ͜ͱ 5SZXJUI3FTPVSDFT -PBO1BUUFSO XJUIPQFO USZ۟Λൈ͚Δ࣌ʹDMPTF ͕ؔͰ͋Δ͜ͱΛ׆͔͠ɺ੍ޚߏจͷΑ͏ʹݟͤΔ
Ϧιʔεͷཧʹֶ͍ͭͯΜͩ͜ͱ 5SZXJUI3FTPVSDFT -PBO1BUUFSO XJUIPQFO USZ۟Λൈ͚Δ࣌ʹDMPTF ͕ؔͰ͋Δ͜ͱΛ׆͔͠ɺ੍ޚߏจͷΑ͏ʹݟͤΔ DMPTFͯ͘͠ΕΔMFUΈ͍ͨͳΠϝʔδ
ฒߦॲཧ
ฒߦॲཧ w ϦΫΤετΛγϦΞϧʹॲཧ͢ΔͱଞͷϦΫΤετΛͨͤͯ͠·͏ w ίϯϏχͷϨδͰ͓หΛԹΊͯΒ͏ྫ͕Πϝʔδ͍͢͠
͋ͨͨΊϦΫΤετ ͋ͨͨ·͓ͬͨห w ͓٬͞Μ͕গͳ͚ΕɺిࢠϨϯδ͕Ͱे·͔ͳ͑Δ ίϯϏχͷϨδΛྫʹߟ͑ͯΈΔ
͋ͨͨΊϦΫΤετ ͋ͨͨ·͓ͬͨห w ͓٬͞Μ͕ଟ͘ͳΔͱɺϨδ͕٧·ͬͯ͠·͏ ίϯϏχͷϨδΛྫʹߟ͑ͯΈΔ
͋ͨͨΊϦΫΤετ ͋ͨͨ·͓ͬͨห w ిࢠϨϯδͷΛ૿ͤղܾʂ ίϯϏχͷϨδΛྫʹߟ͑ͯΈΔ
5ISFBE &YFDVUPS4FSWJDF
5ISFBE class HogeThread extends Thread { public void run() {
// Կ͔ඇಉظʹ࣮ߦ͍ͨ͠ॲཧ } } HogeThread h = new HogeThread(); h.start(); class FugaRunnable implements Runnable { public void run() { // Կ͔ඇಉظʹ࣮ߦ͍ͨ͠ॲཧ } } FugaRunnable f = new Thread(new FugaRunnable()); f.start(); 5ISFBEΛFYUFOET3VOOBCMFΛJNQMFNFOUT
5ISFBE public class WorkerThread extends Thread { private Socket socket;
private RequestParser parser; private RequestHandler handler; public WorkerThread( Socket socket, RequestParser parser, RequestHandler handler) { ... 5ISFBEͷఆٛ 5ISFBEͷىಈ Thread worker = new WorkerThread(socket, parser, handler); worker.start();
&YFDVUPS4FSWJDF ExecutorService cachedPool = Executors.newCachedThreadPool(); cachedPool.execute(runnable); ExecutorService fixedPool = Executors.newFixedThreadPool(4);
fixedPool.execute(runnable); w ΑΓߴਫ४ͳฒྻॲཧͷͨΊͷΈ w εϨουϓʔϧͷछྨࢦఆͰ͖Δ
'VUVSF
'VUVSF w 'VUVSFBQQMZ͞ΕͨॲཧΛඇಉظʹ࣮ߦ w ͍ͭͲͷΑ͏ʹඇಉظʹ࣮ߦ͢Δ͔&YFDVUJPO$POUFYU࣍ୈ import scala.concurrent.Future // ForkJoinPoolɺσϑΥϧτͰίΞͷฒྻͰॲཧ import
scala.concurrent.ExecutionContext.Implicits.global val result: Future[User] = Future { // .applyলུͰ͖Δ userRepository.fetch(userId) } result.map(user => user.id) result.flatMap(user => tweetRepository.fetch(user.id))
&YFDVUJPO$POUFYUͲ͏ड͚औΔʁ w 'VUVSFBQQMZʹҾϒϩοΫ͕ͭ w ͭͷҾϒϩοΫͰ&YFDVUJPO$POUFYUΛड͚औΔ object Future { ... def
apply[T](body: => T)(implicit executor: ExecutionContext): Future[T] = unit.map(_ => body) ... } Future { userRepository.fetch(user) } // ↑Future#applyͷݺͼग़͠
8IBUͱ)PXͷ w ୈҰҾϒϩοΫlCPEZ5z w 8IBUʮԿΛ࣮ߦ͢Δ͔ʯ w ୈೋҾϒϩοΫlJNQMJDJUFYFDVUPS&YFDVUJPO$POUFYUz w )PXʮͲͷΑ͏ʹ࣮ߦ͢Δ͔ʯ w
JNQMJDJUΩʔϫʔυ͕͍͍ͭͯΔͷͰɺ໌ࣔతʹҾͱͯ͢͠ඞཁͳ͠ w 'VUVSF EP4PNFUIJOH FYFDVUPS object Future { ... def apply[T](body: => T)(implicit executor: ExecutionContext): Future[T] = unit.map(_ => body) ... }
JNQMJDJU8IBUͱ)PXͷ w )PX͕ڊେʹͳΔͱɺίʔυͷຊདྷͷҙਤ͕ຒΕͯ͠·͏ w JNQMJDJUͷେ͖ͳϞνϕʔγϣϯ)PXͷӅณ w 8IBUͱ)PXΛ͢Δ͜ͱͰɺతΛతʹࣔ͢͜ͱ͕Ͱ͖Δ val values: Seq[(String,
Option[Int])] val sorted = sort(values)( tuple2Comparator( stringComparator, optionComparator(intComparator))) val sorted = sort(values) // implicit
IUUQHBLV[[[[HJUIVCJPTMJEFTJNQMJDJU@SFJOUSPEVDUJPO
UISFBE
$MPKVSFͷฒߦॲཧؔ w $MPKVSFͷฒߦॲཧؔͨ͘͞Μ͋Δ w HP w UISFBE w TFOE w
TFOEPGG w GVUVSF w FUD
$MPKVSFͷฒߦॲཧؔ εϨουϓʔϧ εϨου TFOE 'JYFE5ISFBE1PPM ίΞ TFOEPGG $BDIFE5ISFBE1PPM ੍ݶͳ͠
GVUVSFGVUVSFDBMM QNBQQDBMMT $BDIFE5ISFBE1PPM ੍ݶͳ͠ HP 'JYFE5ISFBE1PPM ίΞ UISFBE UISFBEDBMM $BDIFE5ISFBE1PPM ੍ݶͳ͠ SFEVDFST 'PSL+PJO1PPM ࣗಈ੍ޚ
*0όϯυ$16όϯυ ΞϓϦέʔγϣϯͷʮෛՙʯɺ *0όϯυͱ$16όϯυͷछྨʹେผ͞ΕΔ w *0όϯυ w *0͕ύϑΥʔϚϯεͷϘτϧωοΫ w $16ʮͪʯ͕ଟ͘ͳΔ w
σΟεΫΞΫηεϦϞʔτ௨৴ͳͲ w$16όϯυ w $16͕ύϑΥʔϚϯεͷϘτϧωοΫ w $16ϑϧՔಇ w େنͳՊֶܭࢉͳͲ
$MPKVSFͷฒߦॲཧؔ εϨουϓʔϧ εϨου TFOE 'JYFE5ISFBE1PPM ίΞ TFOEPGG $BDIFE5ISFBE1PPM ੍ݶͳ͠
GVUVSFGVUVSFDBMM QNBQQDBMMT $BDIFE5ISFBE1PPM ੍ݶͳ͠ HP 'JYFE5ISFBE1PPM ίΞ UISFBE UISFBEDBMM $BDIFE5ISFBE1PPM ੍ݶͳ͠ SFEVDFST 'PSL+PJO1PPM ࣗಈ੍ޚ
$MPKVSFͷฒߦॲཧؔ εϨουϓʔϧ εϨου TFOE 'JYFE5ISFBE1PPM ίΞ TFOEPGG $BDIFE5ISFBE1PPM ੍ݶͳ͠
GVUVSFGVUVSFDBMM QNBQQDBMMT $BDIFE5ISFBE1PPM ੍ݶͳ͠ HP 'JYFE5ISFBE1PPM ίΞ UISFBE UISFBEDBMM $BDIFE5ISFBE1PPM ੍ݶͳ͠ SFEVDFST 'PSL+PJO1PPM ࣗಈ੍ޚ
UISFBE (thread (with-open [s socket in (.getInputStream s) out (.getOutputStream
s)] (-> (request-parser/from-input-stream in) (request-handler/handle-request) (response-writer/write out)))) $BDIFE5ISFBE1PPMΛͬͨฒྻॲཧ
ฒߦॲཧʹֶ͍ͭͯΜͩ͜ͱ
ฒߦॲཧʹֶ͍ͭͯΜͩ͜ͱ 5ISFBE &YFDVUPS4FSWJDF
ฒߦॲཧʹֶ͍ͭͯΜͩ͜ͱ 5ISFBE &YFDVUPS4FSWJDF FYUFOET5ISFBEJNQMFNFOUT3VOOBCMF
ฒߦॲཧʹֶ͍ͭͯΜͩ͜ͱ 5ISFBE &YFDVUPS4FSWJDF 'VUVSF FYUFOET5ISFBEJNQMFNFOUT3VOOBCMF
ฒߦॲཧʹֶ͍ͭͯΜͩ͜ͱ 5ISFBE &YFDVUPS4FSWJDF 'VUVSF FYUFOET5ISFBEJNQMFNFOUT3VOOBCMF 5ISFBE্ཱͪ͛Ͱͳ͍ɻ Ͳ͏࣮ߦ͢Δ͔&YFDVUJPO$POUFYU࣍ୈɻ
ฒߦॲཧʹֶ͍ͭͯΜͩ͜ͱ 5ISFBE &YFDVUPS4FSWJDF 'VUVSF UISFBE FYUFOET5ISFBEJNQMFNFOUT3VOOBCMF 5ISFBE্ཱͪ͛Ͱͳ͍ɻ Ͳ͏࣮ߦ͢Δ͔&YFDVUJPO$POUFYU࣍ୈɻ
ฒߦॲཧʹֶ͍ͭͯΜͩ͜ͱ 5ISFBE &YFDVUPS4FSWJDF 'VUVSF UISFBE FYUFOET5ISFBEJNQMFNFOUT3VOOBCMF 5ISFBE্ཱͪ͛Ͱͳ͍ɻ Ͳ͏࣮ߦ͢Δ͔&YFDVUJPO$POUFYU࣍ୈɻ *0$16όϯυ͔Λҙࣝ͠Α͏
8FCαʔόʔΛ࡞ͬͯ ԿΛಘͨʁ
ͪΐͬͱਂ͘જΔ༐ؾ
ϓϩάϥϛϯάݴޠ8FCϑϨʔϜϫʔΫ ͜Ε·ͰͲͷΑ͏ʹมԽ͖͔ͯͨ͠ʁ
ʮ3FBEBCMF4DBMBʯJO4DBMB.BUTVSJ !HBLV[[[[ ϓϩάϥϛϯάݴޠͷਐԽͷྺ࢙ɺ ͍͔ʹ)PXΛӅ͍ͯ͠ 8IBUΛతʹදݱͰ͖ΔΑ͏ʹ͢Δ͔ɺͷ ྺ࢙Ͱ͋Γ·͢
ྫ͑+BWBͷ4USFBN"1*
ྫ͑+BWBͷ4USFBN"1* ʮϦετΛॱ൪ʹ͞Β͍ɺ ɹۮͩͬͨΒϦετʹ٧ΊΔʯ ɹͱ͍͏खଓ͖ʢ)PXʣ
ྫ͑+BWBͷ4USFBN"1* खଓ͖ΛӅṭ͠ɺ ʮۮͷΈͷϦετΛ࡞Δʯ ɹͱ͍͏తʢ8IBUʣʹϑΥʔΧε
ϑϨʔϜϫʔΫϥΠϒϥϦͰ w ྫ %#͔ΒϨίʔυΛ݅औಘ w ʮ%#ʹͲ͏͍͏42-Λൃߦ͢Δ͔ʯͱ͍͏)PXΛӅณ͠ɺ ʮ+PCΛ*%ͰϑΟϧλϦϯάͯ݅͠औಘ͢Δʯͱ͍͏8IBUΛදݱ
ͦͷҰํͰ͜Μͳ͜ͱ w ؆୯ͦ͏ʹʮݟ͑ΔʯϑϧελοΫ8FCϑϨʔϜϫʔΫ w ͪΐͬͱ͍͜͜͠ͱΛΖ͏ͱ͢Δͱɺ্͙͢ख͍͔͘ͳ͘ͳΔ w ʮ)551ϨεϙϯεϔομΛݟΖʯ w ʮ$POUFOU5ZQF͕PDUFUTUSFBN͔ͩΒʜʯ w
ʮNVMUJQBSUGPSNEBUB͕ʜʯ w ʮ+PJOͨͭ͠Γ͕αϒΫΤϦʹͳͬͯΔͷͰʁʯ w ʮ42-ͷ࣮ߦܭը͕ʜʯ
ʮΫϥʔΫͷୈࡾ๏ଇʯΞʔαʔɾ$ɾΫϥʔΫ ߴʹൃୡٕͨ͠ज़ɺ ຐ๏ͱݟ͚͕͔ͭͳ͍
ͳͥʮϋϚΔʯͷ͔ʁ w υΩϡϝϯτͷαϯϓϧίʔυWTʮ࣮ઓʯͷίʔυ w ྆ऀͷဃநԽͷϨΠϠʔΛॏͶΔ΄Ͳେ͖͘ͳΔ w ݁ہԼͷϨΠϠʔͷࣝΛ͍ͬͯΔඞཁ͕͋Δ
ʮ࿙Εͷ͋ΔநԽͷ๏ଇʯ w CZ+PFM4QPMTLZ w நԽͱɺҰʹ͖֓͢೦ΛݮΒ͢͜ͱɺ ͦͷΈͷ͜ͱ w நԽͯ͢ɺఔͷࠩͦ͋͜Εɺ࿙Ε͕͋Δ IUUQTDPNNPOTXJLJNFEJBPSHXJLJ 'JMF+PFM@TQPMTLZ@PO@@TFQU@KQH
8FCϑϨʔϜϫʔΫͷʮநԽͷ࿙Εʯ w ϑϧελοΫͳ8FCϑϨʔϜϫʔΫ࿙Ε͕ݦஶ w ໘ͳ࡞ۀΛநԽ͠ɺ࡞ۀΛޮԽͯ͘͠ΕΔ w ͔͠͠໘ͳ෦ΛશʹӅณͯ͘͠ΕΔΘ͚Ͱͳ͍ w ͋͘·ͰʮޮԽʯͷͨΊͷநԽͰ͋Γɺ ʮԿ͕ى͖͍ͯΔ͔ʯΛҙࣝ͢Δඞཁ͕͋Δ
w )551ɺ42-ɺ$16ɺϝϞϦɺ*0ɺωοτϫʔΫɺFUD
࿙Εͷ͋ΔநԽͰى͖Δ͜ͱ w ϓϩάϥϛϯάݴޠ8FCϑϨʔϜϫʔΫɺநԽʹΑͬͯɺ )PXͰͳ͘8IBUʹूதͰ͖ΔΑ͏ʹਐԽ͍ͯ͘͠ w 8IBUʹूதͰ͖Δརେ͖͍͕ɺ ͦͷநԽඞͣ͠શͰͳ͘ɺ ݁ہԼͷϨΠϠʔͷ)PXΛΒͳ͍ͱઌʹਐΊͳ͍͜ͱ͕͋Δ
ʮ+PFMPO4PGUXBSFʯ+PFM4QPMTLZ ࿙Εͷ͋ΔநԽͷ๏ଇʹ͏·͘ରॲ͢Δ །Ұͷํ๏ɺͦͷநԽ͕ͲͷΑ͏ʹػೳ͠ɺ ͦΕ͕ԿΛநԽ͍ͯ͠Δͷ͔ΛֶͿ͜ͱͩɻ
ಘͨͷͪΐͬͱਂ͘જΔ༐ؾ w ʮ࿙Εͷ͋ΔநԽʯͷͱͰɺղܾͷͨΊʹ ීஈ৮Δٕज़ͷԼͷϨΠϠʔʹજΔ͜ͱ͕ආ͚ΒΕͳ͍ ͔ͭɺ๛ͳใ͕͋ΔͱݶΒͳ͍ w 8FCαʔόʔΛ࡞Δ͜ͱͰɺ8FCϑϨʔϜϫʔΫ͕ͲΜͳࣄΛ ͍ͯ͠Δ͔ͳΜͱͳ͔͘ΔΑ͏ʹ w ӳޠͷҰ࣍ใʹͨΔ͕͍ͤͭͨ͘͜ͱͰɺ
ະ༁ͷ৽͍ٕ͠ज़ͷυΩϡϝϯτͳͲԲͤͣಡΊΔΑ͏ʹ w ʮࣄͰ͍ͬͯΔϑϨʔϜϫʔΫϛυϧΣΞͷίʔυ ಡΜͰΈΑ͏ɻ͋ΘΑ͘ίϯτϦϏϡʔτͯ͠ΈΑ͏ʯͱ ͪΐͬͱਂ͘જͬͯΈΔ༐ؾˍڵຯΛ͖͔͚࣋ͭͬʹ
8FCαʔόʔΛ࡞ͬͯΈΔ͜ͱ͕ɺ Έͳ͞Μͷʮਂ͍ʯΤϯδχΞͷΩϟϦΞΛ ܗ࡞Δ͖͔͚ͬʹͳΕ͏Ε͍͠Ͱ͢
🙏 ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ
ʢ࣌ؒʹ༨༟͕͋Εʣ ίʔυϦʔσΟϯάλΠϜʂ
None
None
None