Save 37% off PRO during our Black Friday Sale! »

新しいプログラミング言語の学び方 HTTPサーバーを作って学ぶ Java, Scala, Clojure

新しいプログラミング言語の学び方 HTTPサーバーを作って学ぶ Java, Scala, Clojure

JJUG CCC 2017 Fallでの発表資料です。

9aba2147bb6e43333fcc42e2afc570f2?s=128

Shunsuke Tadokoro

November 24, 2017
Tweet

Transcript

  1. DDD@H ৽͍͠ϓϩάϥϛϯάݴޠͷֶͼํ )551αʔόʔΛ࡞ֶͬͯͿ
 +BWB 4DBMB $MPKVSF ++6($$$'BMM !UPEPLS ָ͍͠

  2. IUUQTUXJUUFSDPNNBUUO@KQTUBUVT

  3. IUUQTUXJUUFSDPNNBUUO@KQTUBUVT

  4. DDD@H DDD@H

  5. DDD@H ୭ͩ ాॴॣ༎!UPEPLS w גࣜձࣾϏζϦʔν4DBMBΤϯδχΞ w ٻਓݕࡧΤϯδϯ8FCΫϩʔϥʔ΍޿ࠂγεςϜ։ൃͳͲ w Ұ෦ͷਓ͔Β͸ΤϞδχΞͱݺ͹Ε͍ͯ·͢ w

    จࣈίʔυͱ͔&NBDT͕޷͖ͳωΦ࿝֐
  6. DDD@H ৽͍͠ϓϩάϥϛϯάݴޠΛֶͿ w εΩϧ΍ϓϩάϥϛϯάελΠϧͷ෯Λ޿͛ΔͨΊ w ७ਮʹָ͠ΈͷͨΊ

  7. DDD@H ֶͿखஈͷҰͭͱͯ͠ )551αʔόʔ։ൃ͕
 ͓͢͢ΊͰ͢

  8. DDD@H

  9. DDD@H

  10. DDD@H

  11. DDD@H ͓࿩͢͠Δ͜ͱ w ͳͥ)551αʔόʔ  w 4DBMB $MPKVSFʹ͍ͭͯ w )551αʔόʔΛ࡞Γͳ͕Βֶ΅͏

    w ͬ͘͟ΓΞʔΩςΫνϟ w ֤ݴޠͰ࣮૷ͯ͠ΈΔ w 4PDLFUͷѻ͍ w ਖ਼نදݱ w Ϧιʔεͷ։์ w ฒྻॲཧ w จࣈྻͷѻ͍ w ·ͱΊ
  12. DDD@H IUUQTHJUIVCDPNUPEPLSTJNQMFIUUQTFSWFS

  13. DDD@H ͳͥ)551αʔόʔʁ

  14. DDD@H ৽͍͠ݴޠΛֶͿ࣌ʹΑ͘΍Δ͜ͱ w )FMMPXPSME 'J[[#V[[Λ΍Δ w ॻ੶ΛಡΉ w 50%0ΞϓϦͳͲ؆୯ͳ8FCαʔϏεΛ࡞Δ w

    FUD
  15. DDD@H ৽͍͠ݴޠΛֶͿ࣌ʹΑ͘΍Δ͜ͱ w )FMMPXPSME 'J[[#V[[Λ΍Δ w ॻ੶ΛಡΉ w 50%0ΞϓϦͳͲ؆୯ͳ8FCαʔϏεΛ࡞Δ w

    FUD
  16. DDD@H 8FCαʔϏεʁ

  17. DDD@H 8FCαʔϏεʹ͸%#͕͋Δ w ͱΓ͋͑ͣ)Ͱྑ͍͔ʜ w .Z42-8PSL#FODIͰ࡞ͬͨ%%-͕ྲྀͤͳ͍ʂ w ϩʔΧϧͷ.Z42-͕ݹ͍ɻCSFXVQEBUFʂ w ͍΍VQHSBEFͩͬͨ

    w %PDLFS ͱ͔͍͏΍ͭͰ .Z42-Λಈ͔͢ͷ͕
 φ΢͍ΜͰ͔͢Ͷ  w IFSPLV͸1PTUHSF42-ͳΜͩͬͨ
  18. DDD@H 8FCαʔϏεʹ͸ը໘͕͋Δ w ͱΓ͋͑ͣద౰ʹCPPUTUSBQͰ࡞Ζ͏ʂ w ΄͏΄͏ɺ4FNBOUJD6*ͷ΄͏͕ΠϚυΩͬΆ͍Β͍͠ w ςϯϓϨʔτΤϯδϯʁ࣌୅͸41"Ͱ͠ΐ w ੜ$44ਏ͍͔Β4BTTʹ͠Α͏

    w 8FCQBDL CBCFMMPBEFS ͳʹͦΕ͓͍͍͠ͷʁ w EJW͕தԝʹدΒͳ͍
  19. DDD@H ͦΕͬͯ΍Γ͍ͨ͜ͱ͚ͩͬʁ

  20. DDD@H %POUTIBWFUIBUZBL w ผʹ%#Λ৮Γ͍ͨΘ͚Ͱ͸ͳ͍ w ผʹը໘Λ࡞Γ͍ͨΘ͚Ͱ͸ͳ͍ w ৽͍͠ݴޠΛֶͼ͍ͨ

  21. DDD@H ͦ͜Ͱ)551αʔόʔͰ͢Α

  22. DDD@H )551αʔόʔͳΒ w %#΍ը໘Λ༻ҙ͢Δखؒͳ͘ɺखܰʹ։ൃ͕࢝ΊΒΕΔ w 8FC։ൃʹඞཁͳཁૉʹͦͦ͜͜Ұ௨Γ৮ΕΒΕΔ w จࣈྻૢ࡞ɺೖग़ྗɺฒྻॲཧͳͲ w ҧ͏ݴޠɺಉ͡࢓༷Ͱ࡞Ε͹ݴޠͷൺֱ΋͠΍͍͢

  23. DDD@H )551αʔόʔͬͯԿͯ͠Δͷʁ

  24. DDD@H )551αʔόʔ͕΍͍ͬͯΔ͜ͱ w ΫϥΠΞϯτ͔Βͷ઀ଓΛ଴ͪड͚ w ΫϥΠΞϯτ͔ΒૹΒΕ͖ͯͨ)551ϦΫΤετΛύʔε w ϦΫΤετʹج͍ͮͯ)551ϨεϙϯεΛੜ੒ w ΫϥΠΞϯτʹϨεϙϯεΛฦ͢

  25. DDD@H )551ͷ࢓༷ w 3'$ʢ3FRVFTU'PS$PNNFOUTʣ w *&5'ʹΑΔٕज़࢓༷ͷอଘɺެ։ܗࣜ w ϓϩτίϧ΍ϑΝΠϧϑΥʔϚοτͳͲ͕த৺ w )551͸3'$d

  26. DDD@H IUUQTUPPMTJFUGPSHIUNMSGD

  27. DDD@H IUUQIUUQXHPSH

  28. DDD@H ؆қͳ࣮૷ͳΒ਺ඦߦఔ౓

  29. DDD@H 1ZUIPOͷ4JNQMF)5514FSWFS w 1ZUIPOͷ4JNQMF)5514FSWFSΛࢀߟʹ͢Δͷ΋̋ w ܥ w ܥ $ python

    -m SimpleHTTPServer $ python -m http.server
  30. DDD@H 4DBMB$MPKVSF

  31. DDD@H 4DBMB

  32. DDD@H 4DBMB w +BWBͱͷ૬ޓӡ༻ੑ w γʔϜϨεͳݺͼग़͠ɺ+BWBඪ४ϥΠϒϥϦͷ࠶ར༻ w ؆ܿੑ w লུՄೳͳߏจɺܕਪ࿦ɺڧྗͳඪ४ϥΠϒϥϦ

    w ந৅౓ͷߴ͍ίʔυɺ৽੍͍͠ޚߏจΛఆٛͰ͖Δදݱྗ w 8IBUͷڧௐɺ)PXͷӅณ w ੩తܕ෇͚ w ݕূՄೳੑɺϦϑΝΫλͷ͠΍͢͞ɺυΩϡϝϯτੑ
  33. DDD@H 4DBMBͬͯόϦόϦͷ
 ؔ਺ܕݴޠͳΜͰ͠ΐ

  34. IUUQTMFBOQVCDPNGQNPSUBMTSFBE

  35. IUUQTMFBOQVCDPNGQNPSUBMTSFBE

  36. DDD@H 1MFBTF EPOUEPUIJTJO4DBMB .BSUJO0EFSTLZ

  37. DDD@H 1MFBTF EPOUEPUIJTJO4DBMB .BSUJO0EFSTLZ ௨শখా޷ઌੜ

  38. DDD@H 4DBMBͷ࡞ऀ 1MFBTF EPOUEPUIJTJO4DBMB .BSUJO0EFSTLZ ௨শখా޷ઌੜ

  39. DDD@H ΦϒδΣΫτࢦ޲ͱؔ਺ܕͷʮ౷߹ʯ w ΦϒδΣΫτࢦ޲ͷ֓೦Ͱؔ਺ܕͷػೳΛղऍ ஋ΦϒδΣΫτ DBTFDMBTT ୅਺తσʔλܕ 001 '1

  40. DDD@H $MPKVSF

  41. DDD@H $MPKVSF w -JTQ w จ๏͕গͳ͍ɺσʔλͱͯ͠ͷίʔυ w ؔ਺ܕϓϩάϥϛϯάͷͨΊͷݴޠ w ୈҰڃؔ਺ɺΠϛϡʔλϒϧͳσʔλߏ଄ɺ࠶ؼతͳϧʔϓ

    w +BWBͱͷ૬ޓӡ༻ੑ w ฒߦॲཧͷͨΊʹઃܭ w 3&1-Λ׆͔ͨ͠ΠϯλϥΫςΟϒΠϯΫϦϝϯλϧͳ ։ൃ
  42. DDD@H ίϯηϓτ͕໘ന͍ w ঢ়ଶʹ͍ͭͯͷߟ͑ํɺ*EFOUJUZ 4UBUF 7BMVFͷ෼཭ w γϯϓϧ͞ʹ͍ͭͯ ͍Ζ͍Ζܹࢗత

  43. DDD@H IUUQCPYPGQBQFSTIBUFOBCMPHDPNFOUSZTJNQMF@NBEF@FBTZ

  44. DDD@H -JTQͷγϯλοΫε ׅހͷ࢝·Γ͔ΒऴΘΓ·Ͱ͕୯Ґ (ԿΒ͔ͷॲཧ ॲཧͷର৅ͳͲ…)

  45. DDD@H $MPKVSF͸Χοίͷछྨ͕ଟ͘ɺಡΈ΍͍͢ ͨͱ͑͹ؔ਺ͷҾ਺ $PNNPO-JTQ 4DIFNF $MPKVSF (defun square (x) (*

    x x)) (define (square x) (* x x)) (defn square [x] (* x x))
  46. DDD@H େৎ෉

  47. DDD@H جຊจ๏Ͱ΢ΥʔϛϯάΞοϓ

  48. DDD@H ࢛ଇԋࢉ 12 + 40 10 - 1 2 *

    3 5 / 2 +BWB 4DBMB (+ 12 40) (- 10 1) (* 2 3) (/ 5 2) ; -> 5/2 ෼਺Λѻ͏Ratioܕ $MPKVSF
  49. DDD@H ม਺એݴ int x = 10; +BWB val x =

    10 val x: Int = 10 4DBMB (def x 10) (let [y 10] (+ y 3)) ; y͸letͷׅހ಺͚ͩͰࢀরͰ͖Δ $MPKVSF
  50. DDD@H ϝιουɾؔ਺એݴ public int f(int x) { return x +

    1; } +BWB (defn f [x] (+ x 1)) $MPKVSF def f(x: Int) = x + 1 4DBMB
  51. DDD@H

  52. DDD@H )551αʔόʔΛ
 ࡞Γͳ͕Βֶ΅͏

  53. DDD@H ࠓճ༻ҙͨ͠)551αʔόʔ w ىಈ͠ɺMPDBMIPTUͷಛఆͷϙʔτͰ)551ϦΫΤετΛ଴ͪड͚Δ w ରԠ͢Δ)551ϦΫΤετϝιου͸(&5ͷΈ
 ͦΕҎ֎ͷϝιου΋(&5ͱΈͳ͢ w QVCMJDσΟϨΫτϦΑΓ্ͷ֊૚΁ͷϦΫΤετʹ͸
 'PSCJEEFOΛฦ͢

    w Ϧιʔεͷ.*.&͸֎෦ϑΝΠϧͰઃఆͰ͖Δ w ϦΫΤετΛϒϩοΫ͠ͳ͍ʢϚϧνεϨουʣ w ,FFQ"MJWF͸͠ͳ͍ɻίωΫγϣϯ͸౎౓DMPTF͢Δ w )551$BDIF͸͠ͳ͍ɻ͸ฦ͞ͳ͍
  54. DDD@H ىಈ w +BWB NWODPNQJMF NWOFYFDKBWB w 4DBMB TCUSVO w

    $MPKVSF MFJOSVO
  55. DDD@H ͭ͘Γʹ͍ͭͯͬ͘͟Γͱ ├── MimeDetector.java ├── Request.java ├── RequestHandler.java ├── RequestParser.java

    ├── Response.java ├── SimpleJavaHttpServer.java └── WorkerThread.java ΞϓϦέʔγϣϯͷΤϯτϦʔϙΠϯτ 3FRVFTU *OQVU4USFBN 3FTQPOTF 0VUQVU4USFBN ϦΫΤετͷύʔε ϦΫΤετͷϋϯυϦϯά Ϩεϙϯεͷ8SJUF
  56. DDD@H ͭ͘Γʹ͍ͭͯͬ͘͟Γͱ ├── MimeDetector.java ├── Request.java ├── RequestHandler.java ├── RequestParser.java

    ├── Response.java ├── SimpleJavaHttpServer.java └── WorkerThread.java )551ϦΫΤετΛύʔε͢Δ 3FRVFTU *OQVU4USFBN 3FTQPOTF 0VUQVU4USFBN ϦΫΤετͷύʔε ϦΫΤετͷϋϯυϦϯά Ϩεϙϯεͷ8SJUF
  57. DDD@H ͭ͘Γʹ͍ͭͯͬ͘͟Γͱ ├── MimeDetector.java ├── Request.java ├── RequestHandler.java ├── RequestParser.java

    ├── Response.java ├── SimpleJavaHttpServer.java └── WorkerThread.java ϦΫΤετΛද͢ΦϒδΣΫτ 3FRVFTU *OQVU4USFBN 3FTQPOTF 0VUQVU4USFBN ϦΫΤετͷύʔε ϦΫΤετͷϋϯυϦϯά Ϩεϙϯεͷ8SJUF
  58. DDD@H ͭ͘Γʹ͍ͭͯͬ͘͟Γͱ ├── MimeDetector.java ├── Request.java ├── RequestHandler.java ├── RequestParser.java

    ├── Response.java ├── SimpleJavaHttpServer.java └── WorkerThread.java ϦΫΤετ͔ΒϨεϙϯεΛੜ੒ 3FRVFTU *OQVU4USFBN 3FTQPOTF 0VUQVU4USFBN ϦΫΤετͷύʔε ϦΫΤετͷϋϯυϦϯά Ϩεϙϯεͷ8SJUF
  59. DDD@H ͭ͘Γʹ͍ͭͯͬ͘͟Γͱ ├── MimeDetector.java ├── Request.java ├── RequestHandler.java ├── RequestParser.java

    ├── Response.java ├── SimpleJavaHttpServer.java └── WorkerThread.java ϨεϙϯεΛද͢ΦϒδΣΫτ 3FRVFTU *OQVU4USFBN 3FTQPOTF 0VUQVU4USFBN ϦΫΤετͷύʔε ϦΫΤετͷϋϯυϦϯά Ϩεϙϯεͷ8SJUF
  60. DDD@H ͭ͘Γʹ͍ͭͯͬ͘͟Γͱ ├── MimeDetector.java ├── Request.java ├── RequestHandler.java ├── RequestParser.java

    ├── Response.java ├── SimpleJavaHttpServer.java └── WorkerThread.java )551ϨεϙϯεΛ8SJUF 3FRVFTU *OQVU4USFBN 3FTQPOTF 0VUQVU4USFBN ϦΫΤετͷύʔε ϦΫΤετͷϋϯυϦϯά Ϩεϙϯεͷ8SJUF
  61. DDD@H ֤ݴޠͰ΍ͬͯΈΔ w 4PDLFUͷѻ͍ w ਖ਼نදݱ w Ϧιʔεͷ։์ w ฒߦॲཧ

    w จࣈྻͷѻ͍
  62. DDD@H ࡞Γ࢝ΊΔίπ w ೉͘͠ߟ͑͗͢ͳ͍ w ॳΊ͔Βߟ͑ํΛࠜຊతʹม͑Δඞཁ͸ͳ͍ w O೥ޙʹ΋͏Ұ౓࡞Γ௚͢ͱ੒௕͕࣮ײͰ͖Δ͔΋

  63. DDD@H 4PDLFUͷѻ͍

  64. DDD@H 4PDLFU

  65. DDD@H 4PDLFU w ௨৴ʹ͓͚ΔΤϯυϙΠϯτΛදݱͨ͠σʔλϞσϧ ֤ΤϯυϙΠϯτΛࣝผ͢Δ̎ͭͷ஋ɺ
 ͢ͳΘͪ*1ΞυϨεͱϙʔτ൪߸͸ɺ
 ଟ͘ͷ৔߹ιέοτ TPDLFU ͱݺ͹ΕΔɻ ʮ6/*9ωοτϫʔΫϓϩάϥϛϯάʯ

  66. DDD@H 4PDLFU௨৴ͷ໛ࣜਤ ΫϥΠΞϯτ αʔόʔ

  67. DDD@H 4PDLFU௨৴ͷ໛ࣜਤ ΫϥΠΞϯτ αʔόʔ αʔόʔιέοτ

  68. DDD@H 4PDLFU௨৴ͷ໛ࣜਤ ΫϥΠΞϯτ αʔόʔ αʔόʔιέοτ ΫϥΠΞϯτιέοτ

  69. DDD@H 4PDLFU௨৴ͷ໛ࣜਤ ΫϥΠΞϯτ αʔόʔ αʔόʔιέοτ ΫϥΠΞϯτιέοτ ઀ଓཁٻ

  70. DDD@H 4PDLFU௨৴ͷ໛ࣜਤ ΫϥΠΞϯτ αʔόʔ αʔόʔιέοτ ΫϥΠΞϯτιέοτ ઀ଓ

  71. DDD@H 4PDLFU௨৴ͷ໛ࣜਤ ΫϥΠΞϯτ αʔόʔ αʔόʔιέοτ ΫϥΠΞϯτιέοτ

  72. DDD@H 4PDLFUͷѻ͍ // αʔόʔιέοτͷੜ੒ ServerSocket serverSocket = new ServerSocket(8080); while

    (true) { // ઀ଓΛ଴ͪड͚Δɻ઀ଓ͞ΕΔ·ͰϒϩοΫɻ Socket socket = serverSocket.accept(); InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); ... } 4JNQMF+BWB)UUQ4FSWFSKBWBʢൈਮʣ
  73. DDD@H 4PDLFUͷѻ͍ // αʔόʔιέοτͷੜ੒ val serverSocket = new ServerSocket(8080) while

    (true) { // ઀ଓΛ଴ͪड͚Δɻ઀ଓ͞ΕΔ·ͰϒϩοΫ val socket = serverSocket.accept val in = s.getInputStream val out = s.getOutputStream ... } 4JNQMF)UUQ4FSWFSTDBMBʢൈਮʣ
  74. DDD@H 4PDLFUͷѻ͍ (let [server-socket (new ServerSocket 8080)] (while true (let

    [socket (.accept server-socket) in (.getInputStream socket) out (.getOutputStream socket)] ...))) DPSFDMKʢൈਮʣ
  75. DDD@H 4PDLFUͷѻ͍ʹֶ͍ͭͯΜͩ͜ͱ w 4FSWFS4PDLFUΦϒδΣΫτΛੜ੒͠ɺ
 ΫϥΠΞϯτ͔Βͷ઀ଓΛBDDFQUͰ଴ͪड͚Δ w 4PDLFUΦϒδΣΫτʢΫϥΠΞϯτιέοτʣ͔Β
 *O0VUQVU4USFBN͕औಘͰ͖Δ w *OQVU4USFBN͔Β)551ϦΫΤετΛ3FBE͠ɺ


    0VUQVU4USFBNʹ)551ϨεϙϯεΛ8SJUF͢Δ
  76. DDD@H ਖ਼نදݱ

  77. DDD@H ਖ਼نදݱ w 4PDLFUͷ*OQVU4USFBNΛ
 ҰߦಡΉ
 ˠSFRVFTUMJOF w ֤ཁૉΛநग़͍ͨ͠

  78. DDD@H ਖ਼نදݱ w 4PDLFUͷ*OQVU4USFBNΛ
 ҰߦಡΉ
 ˠSFRVFTUMJOF w ֤ཁૉΛநग़͍ͨ͠

  79. DDD@H w 4PDLFUͷ*OQVU4USFBNΛ
 ҰߦಡΉ
 ˠSFRVFTUMJOF w ֤ཁૉΛநग़͍ͨ͠ ਖ਼نදݱ

  80. DDD@H ໊લ෇͖άϧʔϓ

  81. DDD@H ໊લ෇͖άϧʔϓ 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 }
  82. DDD@H w ϦΫΤετϥΠϯͷ֤ཁૉʹ໊લΛ෇͚ͯநग़ 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); } ໊લ෇͖άϧʔϓ 3FRVFTU1BSTFSKBWBʢൈਮʣ
  83. DDD@H ύλʔϯϚον S

  84. DDD@H ύλʔϯϚον 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"$x͸Int" // 1͸Int x: String => s"$x͸String" x => s"$x͸???" }
  85. DDD@H ύλʔϯϚον w ࠓޙ+BWBʹ΋ೖΔ͔΋͠Εͳ͍ IUUQPQFOKELKBWBOFUKFQT

  86. DDD@H ύλʔϯϚον w ਖ਼نදݱΦϒδΣΫτʹରͯ͠΋Ϛονͤ͞ΒΕΔ val pattern = "(.+)/(.+)/(.+)".r //.rͰregexܕ "2017/11/18"

    match { case pattern(y, m, d) => s"${y}೥${m}݄${d}೔" case _ => "???" }
  87. DDD@H ύλʔϯϚον val pattern = "(.+) (.+) (.+)".r requestLine match

    { case pattern(method, path, version) => Some(Request(method, path, version)) case _ => None } 3FRVFTU1BSTFSTDBMBʢൈਮʣ
  88. DDD@H 0QUJPOܕ requestLine match { case pattern(method, path, version) =>

    Some(Request(method, path, version)) case _ => None } w +BWBͰ͍͏0QUJPOBM w 4PNFͱ/POF͔ΒͳΔܕ w ஋͕͋Δ͔ͳ͍͔෼͔Βͳ͍ঢ়ଶΛද͢ w ஋͕ଘࡏ͢Δ͔ͷνΣοΫΛڧ੍Ͱ͖Δ
  89. DDD@H  SFpOE

  90. DDD@H 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")
  91. DDD@H [JQNBQ w ڧྗͳίϨΫγϣϯϥΠϒϥϦ͸$MPKVSFͷಛ௃ w [JQNBQ͸ͭͷίϨΫγϣϯ͔Β.BQΛ࡞Δ w $MPKVSFͰ͸ΫϥεΑΓ΋.BQΛ޷Ή (zipmap [:a

    :b :c] [1 2 3]) ;; => {:a 1, :b 2, :c 3}
  92. DDD@H SFpOE [JQNBQ (let [line (.readLine reader)] (zipmap [:method :path

    :version] (rest (re-find #"(.+) (.+) (.+)" line)))) ;; => {:method "GET", :path "/", :version "HTTP/1.1"} SFRVFTU@QBSTFSDMKʢൈਮʣ
  93. DDD@H SFpOE [JQNBQ (let [line (.readLine reader)] (zipmap [:method :path

    :version] (rest (re-find #"(.+) (.+) (.+)" line)))) ;; => {:method "GET", :path "/", :version "HTTP/1.1"} SFRVFTU@QBSTFSDMKʢൈਮʣ <NFUIPEQBUIWFSTJPO> <(&5)551>
  94. DDD@H SFpOE [JQNBQ (let [line (.readLine reader)] (zipmap [:method :path

    :version] (rest (re-find #"(.+) (.+) (.+)" line)))) ;; => {:method "GET", :path "/", :version "HTTP/1.1"} SFRVFTU@QBSTFSDMKʢൈਮʣ <NFUIPEQBUIWFSTJPO> <(&5)551>
  95. DDD@H ਖ਼نදݱʹֶ͍ͭͯΜͩ͜ͱ ໊લ෇͖άϧʔϓ ύλʔϯϚον
 S SFpOE
  ఴࣈͰΞΫηε͢ΔΑΓ҆৺ ߏ଄ͷ෼ղʹ΋࢖͑Δ ݁Ռ͸ίϨΫγϣϯɺڧྗͳίϨΫγϣϯૢ࡞ͱ૊Έ߹Θͤͯ

  96. DDD@H Ϧιʔεͷղ์

  97. DDD@H Ϧιʔεͷղ์ w ετϦʔϜ΍%#ίωΫγϣϯɺιέοτ͸
 ࢖͍ऴΘͬͨΒDMPTF w ๨ΕΔͱϝϞϦϦʔΫͷݪҼʹͳΔ͜ͱ͕͋Δ w खͰDMPTFॻ͖ͨ͘ͳ͍ʂ

  98. DDD@H 5SZXJUI3FTPVSDFT

  99. DDD@H 5SZXJUI3FTPVSDFT try (InputStream in = new FileInputStream(file)) { //

    Կ͔ϦιʔεΛѻ͏ॲཧ } // try۟Λൈ͚ͨΒclose w USZ۟Λൈ͚ͨΒࣗಈͰDMPTF w ର৅͸KBWBJP$MPTFBCMF 
 KBWBMBOH"VUP$MPTFBCMFͷ࣮૷Ϋϥε
  100. DDD@H -PBO1BUUFSO

  101. DDD@H -PBO1BUUFSO w ʮआΓͨΒฦ͢ʯΛ࣮֬ʹߦ͏ w ੍ޚߏ଄ͷΑ͏ʹݟ͔͚࣮ͤͯ͸ϝιου val reader = new

    BufferedReader(...) using(reader) { r => // readerΛ࢖ͬͨԿ͔ͷॲཧ } // ϒϩοΫΛൈ͚ͨΒreader͸close͞Ε͍ͯΔ
  102. DDD@H -PBO1BUUFSOͷ࣮૷ def using[A, R <: Closeable](resource: R)(f: R =>

    A): A = { try { f(resource) } finally { resource.close() } }
  103. DDD@H -PBO1BUUFSOͷ࣮૷ def using[A, R <: Closeable](resource: R)(f: R =>

    A): A = { try { f(resource) } finally { resource.close() } } ܕม਺3͸$MPTFBCMF
  104. DDD@H -PBO1BUUFSOͷ࣮૷ def using[A, R <: Closeable](resource: R)(f: R =>

    A): A = { try { f(resource) } finally { resource.close() } } 3ܕͷԿ͔Λड͚औΓɺԿΒ͔ͷܕ"Λฦؔ͢਺ΛҾ਺ʹͱΔ
  105. DDD@H -PBO1BUUFSOͷ࣮૷ def using[A, R <: Closeable](resource: R)(f: R =>

    A): A = { try { f(resource) } finally { resource.close() } } Ϧιʔεʹରͯؔ͠਺Λద༻
  106. DDD@H -PBO1BUUFSOͷ࣮૷ def using[A, R <: Closeable](resource: R)(f: R =>

    A): A = { try { f(resource) } finally { resource.close() } } ࠷ޙʹDMPTF
  107. DDD@H ׅހ ͱதׅހ\^ "hoge".startsWith{"ho"} // ͋·Γ΍Βͳ͍ "hoge".replace{"ho", "fu"} // Ͱ͖ͳ͍

    "hoge" map { c => c.someFunc ... } // Α͘΍Δ w Ҿ਺͕Ұ͚ͭͩͷ৔߹ɺׅހΛதׅހͰॻ͍ͯ΋ྑ͍ w Ҿ਺ʹؔ਺Λ౉͢৔߹ɺதׅހΛ࢖͏͜ͱ͕Α͋͘Δ
  108. DDD@H -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)) } 4JNQMF)UUQ4FSWFSTDBMBʢൈਮʣ
  109. DDD@H XJUIPQFO

  110. DDD@H w -PBO1BUUFSOʹࣅͨXJUIPQFOͱ͍͏ϚΫϩ w MFUͱಉ͡Α͏ͳײ͡Ͱ࢖͏ XJUIPQFO (with-open [f (io/file "test.txt")]

    ...)
  111. DDD@H XJUIPQFO (with-open [s socket] (-> (request-parser/from-input-stream (.getInputStream s)) (request-handler/handle-request)

    (response-writer/write (.getOutputStream s)))) DPSFDMKʢൈਮʣ
  112. DDD@H Ϧιʔεͷղ์ʹֶ͍ͭͯΜͩ͜ͱ 5SZXJUI3FTPVSDFT -PBO1BUUFSO XJUIPQFO USZ۟Λൈ͚Δ࣌ʹDMPTF ؔ਺͕஋Ͱ͋Δ͜ͱΛ׆͔͠ɺ੍ޚߏจͷΑ͏ʹݟͤΔ DMPTFͯ͘͠ΕΔMFUΈ͍ͨͳΠϝʔδ

  113. DDD@H ฒߦॲཧ

  114. DDD@H ฒߦॲཧ w ϦΫΤετΛγϦΞϧʹॲཧ͢ΔͱଞͷϦΫΤετΛ଴ͨͤͯ͠·͏ w ͳͷͰϦΫΤετΛड͚෇͚ͨઌ͸ฒߦʹॲཧ͢Δ w +7.ݴޠͳͷͰϚϧνεϨουͰ

  115. DDD@H 5ISFBE &YFDVUPS4FSWJDF

  116. DDD@H 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
  117. DDD@H 5ISFBE public class WorkerThread extends Thread { private Socket

    socket; private RequestParser parser; private RequestHandler handler; public WorkerThread( Socket socket, RequestParser parser, RequestHandler handler) { ... 8PSLFS5ISFBEKBWBʢൈਮʣ 4JNQMF+BWB)UUQ4FSWFSKBWBʢൈਮʣ Thread worker = new WorkerThread(socket, parser, handler); worker.start();
  118. DDD@H &YFDVUPS4FSWJDF ExecutorService cachedPool = Executors.newCachedThreadPool(); cachedPool.execute(runnable); ExecutorService fixedPool =

    Executors.newFixedThreadPool(4); fixedPool.execute(runnable); w ʮλεΫʯΛผεϨουͰॲཧ͢ΔͨΊͷ࢓૊Έ w εϨουϓʔϧͷछྨΛࢦఆͰ͖Δ
  119. DDD@H 'VUVSF

  120. DDD@H 'VUVSF w 'VUVSFBQQMZ͸౉͞ΕͨॲཧΛඇಉظʹ࣮ߦ w ͍ͭͲͷΑ͏ʹඇಉظʹ࣮ߦ͢Δ͔͸&YFDVUJPO$POUFYU࣍ୈ import scala.concurrent.Future // ForkJoinPoolɺσϑΥϧτͰ͸ίΞ਺෼ͷฒྻ౓Ͱॲཧ

    import scala.concurrent.ExecutionContext. Implicits.global val result: Future[User] = Future { userRepository.fetch(userId) } result.map(user => user.id)
  121. DDD@H &YFDVUJPO$POUFYU͸Ͳ͏ड͚औΔʁ w 'VUVSFBQQMZʹ͸Ҿ਺ϒϩοΫ͕ͭ w ͭ໨ͷҾ਺ϒϩοΫͰ&YFDVUJPO$POUFYUΛड͚औΔ object Future { ...

    def apply[T](body: =>T)(implicit executor: ExecutionContext) } Future { userRepository.fetch(user) } Future.apply( userRepository.fetch(user) )
  122. DDD@H 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
  123. DDD@H IUUQHBLV[[[[HJUIVCJPTMJEFTJNQMJDJU@SFJOUSPEVDUJPO

  124. DDD@H UISFBE

  125. DDD@H $MPKVSFͷฒߦॲཧؔ਺ w $MPKVSFͷฒߦॲཧؔ਺͸ͨ͘͞Μ͋Δ w HP w UISFBE w TFOE

    w TFOEPGG w GVUVSF w FUD
  126. DDD@H IUUQUZBOPTIFMpODDPNQPTUDMPKVSFDPODVSSFOU

  127. DDD@H $MPKVSFͷฒߦॲཧؔ਺ εϨουϓʔϧ εϨου਺ TFOE 'JYFE5ISFBE1PPM  ίΞ਺ TFOEPGG $BDIFE5ISFBE1PPM

    ੍ݶͳ͠ GVUVSFGVUVSFDBMM QNBQQDBMMT $BDIFE5ISFBE1PPM ੍ݶͳ͠ HP 'JYFE5ISFBE1PPM ίΞ਺   UISFBE
 UISFBEDBMM $BDIFE5ISFBE1PPM ੍ݶͳ͠ SFEVDFST 'PSL+PJO1PPM ࣗಈ੍ޚ IUUQUZBOPTIFMpODDPNQPTUDMPKVSFDPODVSSFOU
  128. DDD@H *0ό΢ϯυ$16ό΢ϯυ w $MPKVSFͷฒߦॲཧؔ਺͸ɺ*0$16ό΢ϯυͷछྨʹେผ *0ό΢ϯυͳॲཧ͸ɺ࣮ߦதͷॲཧ͕$16ΑΓ΋*0ॲཧʹ
 ڧ͘ґଘ͠·͢ɻ%#ΞΫηεͱ͔ϦϞʔτ௨৴ͱ͔Ͱ͢Ͷɻ
 ผεϨουͰ͜ͷॲཧΛ࣮ߦͨ͠৔߹ɺεϨου͸େ෦෼Λɺ
 *0ॲཧ଴ͪঢ়ଶͰա͝͠·͢ɻ $16ό΢ϯυͳॲཧ͸ɺ్தʹ*0଴ͪͷΑ͏ͳʮ଴ػʯ͕
 ൃੜͤͣɺ$16ΛͿΜճ͠ଓ͚ΔΑ͏ͳॲཧͰ͢ɻ


    શσʔλ͕ϝϞϦʹࡌ͍ͬͯͯɺ$16͕ϑϧՔಇͰͦΕΒΛ
 ॲཧ͢ΔΑ͏ͳέʔεͰ͢ɻ IUUQUZBOPTIFMpODDPNQPTUDMPKVSFDPODVSSFOU
  129. DDD@H $MPKVSFͷฒߦॲཧؔ਺ εϨουϓʔϧ εϨου਺ TFOE 'JYFE5ISFBE1PPM  ίΞ਺ TFOEPGG $BDIFE5ISFBE1PPM

    ੍ݶͳ͠ GVUVSFGVUVSFDBMM QNBQQDBMMT $BDIFE5ISFBE1PPM ੍ݶͳ͠ HP 'JYFE5ISFBE1PPM ίΞ਺   UISFBE
 UISFBEDBMM $BDIFE5ISFBE1PPM ੍ݶͳ͠ SFEVDFST 'PSL+PJO1PPM ࣗಈ੍ޚ IUUQUZBOPTIFMpODDPNQPTUDMPKVSFDPODVSSFOU
  130. DDD@H $MPKVSFͷฒߦॲཧؔ਺ εϨουϓʔϧ εϨου਺ TFOE 'JYFE5ISFBE1PPM  ίΞ਺ TFOEPGG $BDIFE5ISFBE1PPM

    ੍ݶͳ͠ GVUVSFGVUVSFDBMM QNBQQDBMMT $BDIFE5ISFBE1PPM ੍ݶͳ͠ HP 'JYFE5ISFBE1PPM ίΞ਺   UISFBE
 UISFBEDBMM $BDIFE5ISFBE1PPM ੍ݶͳ͠ SFEVDFST 'PSL+PJO1PPM ࣗಈ੍ޚ IUUQUZBOPTIFMpODDPNQPTUDMPKVSFDPODVSSFOU
  131. DDD@H 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)))) DPSFDMKʢൈਮʣ
  132. DDD@H ฒߦॲཧʹֶ͍ͭͯΜͩ͜ͱ 5ISFBE
 &YFDVUPS4FSWJDF 'VUVSF UISFBE FYUFOET5ISFBEJNQMFNFOUT3VOOBCMF 5ISFBE্ཱͪ͛Ͱ͸ͳ͍ɻ
 Ͳ͏࣮ߦ͢Δ͔͸&YFDVUJPO$POUFYU࣍ୈɻ
 JNQMJDJUʹΑΔ)PXͷӅณɻ

    *0$16ό΢ϯυ͔Λҙࣝ͠Α͏
  133. DDD@H จࣈྻͷѻ͍

  134. DDD@H จࣈྻ݁߹ w ϨεϙϯεʢΦϒδΣΫτϚοϓʣ͔Β
 )551ϨεϙϯεϔομΛ૊Έཱ͍ͯͨ public class Response { public

    final Status status; public final String contentType; public final int contentLength; public final byte[] body; }
  135. DDD@H  4USJOH#VJMEFS

  136. DDD@H 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; 3FTQPOTFKBWBʢൈਮʣ ࠷దԽ͞ΕΔ͔ࣗ৴͕ͳ͚Ε͹KBWBQD
  137. DDD@H 4USJOH*OUFSQPMBUJPO 5SJQMF2VPUF

  138. DDD@H 4USJOH*OUFSQPMBUJPO w จࣈྻϦςϥϧͷલʹTΛ෇͚Δͱɺม਺Λల։Ͱ͖Δ val price = 1000 s"Price is

    $price" // => Price is 1000
  139. DDD@H 5SJQMF2VPUF "Hello triple quote!\nHello stripMargin!" """Hello triple quote! Hello

    stripMargin!""" """|Hello triple quote! |Hello stripMargin!""".stripMargin w վߦΛؚΉจࣈྻΛຒΊࠐΉʹ͸ɺΛ࢖͏ w ΠϯσϯτΛଗ͑Δʹ͸Πϯσϯτจࣈ c ͱTUSJQ.BSHJOΛ࢖͏
  140. DDD@H 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 3FTQPOTFTDBMBʢൈਮʣ
  141. DDD@H TUS

  142. DDD@H 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
  143. DDD@H 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)] ...) SFTQPOTF@XSJUFSDMKʢൈਮʣ
  144. DDD@H จࣈྻ݁߹ʹֶ͍ͭͯΜͩ͜ͱ 
 4USJOH#VJMEFS 4USJOH*OUFSQPMBUJPO
 5SJQMF2VPUF TUS KBWBQD ͪΐͬͱͨ͠ςϯϓϨʔτΤϯδϯΈ͍ͨʹ࢖͑Δ ָ͞͸4ࣜͳΒͰ͸ɻͪΐͬͱ-JTQ͕޷͖ʹͳΔ

  145. DDD@H ֤ݴޠͰ΍ͬͯΈͨ w 4PDLFUͷѻ͍ w ਖ਼نදݱ w Ϧιʔεͷ։์ w ฒߦॲཧ

    w จࣈྻͷѻ͍
  146. DDD@H ·ͱΊ

  147. DDD@H )551αʔόʔΛ࡞ͬͯݴޠΛֶ΅͏ w %#΍ը໘Λ༻ҙ͢Δखؒͳ͘ɺखܰʹ։ൃ͕࢝ΊΒΕΔ w 8FC։ൃʹඞཁͳཁૉʹͦͦ͜͜Ұ௨Γ৮ΕΒΕΔ w จࣈྻૢ࡞ɺೖग़ྗɺฒྻॲཧͳͲ w ࠷ॳ͸೉͘͠ߟ͑͗͢ͳ͍ɻ


    ॳΊ͔Βߟ͑ํΛࠜຊతʹม͑Δඞཁ͸ͳ͍ w طʹ஌͍ͬͯΔ͜ͱͱEJGGΛͱͬͯΈΑ͏ w ͦͷݴޠͷੈք؍Λ஌Δख͕͔Γ͕ͦͷEJGGʹ͋Δ͔΋
  148. DDD@H w ڭཆͱͯ͠ͷ$MPKVSFʢճ໨ظ೔ະఆʣ w ڭཆͱͯ͠ͷ4DBMBʢ༧ఆʣ w DPOQBTTͰ%$VCFͷϝϯόʔʹͳΔͱ
 ͓஌Β͕ͤಧ͖·͢ ڭཆγϦʔζ༧ఆ͍ͯ͠·͢

  149. DDD@H (PPE$PEJOH