$30 off During Our Annual Pro Sale. View Details »

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

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

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

Shunsuke Tadokoro

November 24, 2017
Tweet

More Decks by Shunsuke Tadokoro

Other Decks in Technology

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