Upgrade to Pro — share decks privately, control downloads, hide ads and more …

わたしがみんなにオススメするBetter JavaとしてのScala

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

わたしがみんなにオススメするBetter JavaとしてのScala

脱!老害

Avatar for Kazumune Katagiri

Kazumune Katagiri

June 25, 2016
Tweet

More Decks by Kazumune Katagiri

Other Decks in Technology

Transcript

  1. ࣗݾ঺հ • ยۅ Ұफ(͔ͨ͗Γ ͔ͣΉͶ) • id:nemuzuka / @nemuzuka •

    Java / JavaScript / Scala • ݸਓࣄۀओ(vss.jp.net)
  2. ࢲ͕Scalaਪ͠ͳཧ༝ • ੩తܕ෇͚ • IDEΛ࢖ͬͯιʔεΛ௥͍΍͍͢ɻίϯύΠϧ࣌ʹΤϥʔݕ஌ɻ҆৺ʂ • Javaͷ࢓༷(JavaEEͱ͔)ʹԊͬͯͯ΋҆৺ײ͕ແ͘ͳ͖ͬͯͨ • JavaEE࣮ߦ؀ڥͷબ୒ࢶ… •

    ݁ہSpring BootͰे෼͡ΌͶʁͰ΋ɺSpringͷόʔδϣϯUPͷ௥ै΋πϥϛ͋Γͦ͏… • ͦ΋ͦ΋ʮJavaʯͩͱएऀͷ৯͍͖͕ͭྑ͘ͳ͍ؾ͕͢Δ(͋͘·Ͱݸਓͷײ૝Ͱ͢) • هड़ྔΛগͳ͘͢Δ͜ͱ͕Ͱ͖Δ • ͍ΖΜͳॴʹࢄΒ͹ΔࣅͨΑ͏ͳ৑௕ͳॲཧΛ؆୯ʹॻ͘͜ͱ͕Ͱ͖Δ • ΤϥʔΛى͜͠ʹ͍͘هड़Λ͠΍͘͢ͳΔ
  3. ࡯ͯ͘͠Ε·͢ -- java String hoge = “NDS48"; Map<Long, String> map

    = new HashMap<>(); map.put(1L, "NDS#48"); MapͬͯݴͬͯΔͷʹɺHashMapͷهड़λϧΠ... ม਺ଆʹܕΛॻ͔ͳͯ͘ࡁΉɻ1ߦͷίʔυهड़ݮΔɻ LLͬΆ͘ॻ͚Δ͚Ͳܕ҆શɻ طʹ༻ҙ͞Ε͍ͯΔϥΠϒϥϦΛ࢖͏ͱ͖ͷهड़ྔ͸ݮΔ (AWSͱ͔) -- scala var hoge = "NDS48" var map = Map[Long,String]() map += 1L -> “NDS#48” var map2 = Map(1L -> "NDS#48") →ॳظ஋͕͋Ε͹Mapͷܕఆٛ͸ෆཁ
  4. ϝιουఆٛʹ͸Ҿ਺ͷܕ͸ඞཁ def max(x:Int, y:Int):Int = { if (x > y)

    { x } else { y } Ҿ਺໊:ܕ ݁Ռܕ ໌ࣔతʹreturnॻ͔ͳͯ͘΋݁ՌΛฦ͢
  5. Ͱ΋ɺ͍Ζ͍ΖলུͰ͖ΔΜͰ͢ def max(x:Int, y:Int):Int = { if (x > y)

    { x } else { y } } def max(x:Int, y:Int):Int = { if (x > y) x else y } def max(x:Int, y:Int):Int = if (x > y) x else y def max(x:Int, y:Int) = if (x > y) x else y ͱ͸͍͑ɺpublicͳϝιουͷ݁Ռܕ͸লུ͠ͳ͍ํ͕࢖͏ਓʹ༏͍͜͠ͱ͕ଟ͍σε 1ߦͰऩ·ΔifจͷதׅހলུՄ 1ߦͰऩ·Δϝιουͷ தׅހলུՄ ݁ՌܕলུՄ
  6. val:࠶୅ೖ͕Ͱ͖ͳ͍ var:࠶୅ೖ͕Ͱ͖Δ val a = "hoge" // a = “NGT48”

    //ίϯύΠϧΤϥʔ ︙ ௕͍ίʔυ ︙ →͜͜Ͱ͸ɺa==“hoge”ΛอূͰ͖Δ var a = "hoge" a = “NGT48” //͜͏͍͏ॲཧ͕ॻ͚Δ ︙ ௕͍ίʔυ ︙ →͜͜Ͱ͸ɺa==“hoge”ΛอূͰ͖ͳ͍ ௕͍ίʔυͷதͰaͷࢀরઌ͕ มߋ͞ΕΔՄೳੑ͕͋Δ valͰ͋Ε͹ɺଞͷॴͰઈରʹมߋ͞Ε͍ͯͳ͍ͱ໌ݴͰ͖ΔΑ͏ʹͳΔ →ιʔείʔυͰલఏ৚݅Λ୲อͰ͖ɺσʔλͷෆ࣮֬ੑΛഉআ͢Δ͜ͱ͕Ͱ͖Δ valΛ࢖͑͹όά͕ى͖ʹ͘͘ͳΔɻ҆৺ʂ
  7. if͸஋Λฦ͢ͷͰɺແཧͳ͘val var fileName = "default.txt" if(!args.isEmpty) fileName = args(0) ͜ͷॻ͖ํͩͱ࠶୅ೖͷඞཁ͕͋Δҝ

    ม਺fileName͸varͰͳ͍ͱ͍͚ͳ͍ val fileName = if(!args.isEmpty) args(0) else “default.txt" ม਺fileNameʹval͕࢖͑Δʂ҆৺ʂ ex.) ը໘͔Β୯Ձ͕ೖྗ͞Εͨ৔߹ɺͦͷ஋ɻ ະೖྗͷ৔߹ɺ঎඼Ϛελ͔Β୯ՁΛܭࢉͯ͠ઃఆ val unitPrice = if(inputUnitPrice.nonEmpty) BigDecimal(inputUnitPrice) else { ʙ঎඼ϚελΛࢀরͯ͠୯ՁΛܭࢉ͢Δॲཧʙ } ͜ͷifจ͸ ୯Ձܾఆʹؔ͢Δॲཧͷ͔ͨ·Γ(unitPriceͷ஋Λઃఆ͢Δॲཧ) ͩͱ༰қʹ૝૾͕ͭ͘(͍͍ͪͪؔ਺ʹ֎ग़͠͠ͳͯ͘΋ߦؒΛಡΈऔΓ΍͍͢)
  8. immutable(ෆม) / mutable(มߋՄೳ) • ओʹSet΍List(ScalaͰ͸SeqͷαϒΫϥε)΍MapΛ࢖͏࣌ʹؾʹ͢Δ • Javaͷjava.util.ArrayList΍java.util.HashMap͸mutable • ཁૉͷมߋ͕Ͱ͖Δ(෭࡞༻Λ࣋ͬͯ͠·͏) •

    Scalaͷscala.List͸immutable • ཁૉͷมߋ͕Ͱ͖ͳ͍(෭࡞༻Λ࣋ͨͳ͍) ཁૉͷมߋ͕Ͱ͖ͳ͍ˠଞͷॴͰઈରʹมߋ͞Ε͍ͯͳ͍ͱ໌ݴͰ͖Δ immutableΛ࢖͑͹όά͕ى͖ʹ͘͘ͳΔɻ҆৺ʂ
  9. ϒϩοΫࣜΛ࢖͏ͱ͜Μͳײ͡ val map = { val m = Map.newBuilder[Long, String]

    m += 1L -> "Hoge" m += 2L -> "Hage" m += 3L -> "Hige" ɾɾɾ m.result() } ϒϩοΫࣜͷதͰ mutableͳMapʹରͯ͠มߋ͠·͢ (DB౳͔Βऔಘͨ͠σʔλΛ ઃఆ͢Δॲཧͱ͔Λهड़͢ΔΠϝʔδ) ͜ΕͰม਺ʮmapʯ͸ valͰimmutableͳMapʹͳΔɻ҆৺ʂ Ͱɺ࠷ޙʹimmutableͳMapʹม׵͢Δ
  10. immutableͳΦϒδΣΫτΛ ؆୯ʹੜ੒Ͱ͖·͢ • ίϯετϥΫλʹࢦఆ͞ΕͨҾ਺͸val෇͖ͱͯ͠ѻ͏ • ಡΈऔΓઐ༻ʹͳΔˠimmutableʂ҆৺ʂDTOʹ࠷దʂ • Πϯελϯεੜ੒࣌ʮnewʯΩʔϫʔυ͍Βͳ͍ʂָνϯʂ • toString/hashCode/equals͕ࣗಈͰ࣮૷͞ΕΔʂcase

    classಉ࢜Λʮ==ʯͰൺֱͰ͖ΔΑ͏ʹͳΔʂ • copyϝιου͕༻ҙ͞ΕΔˠϓϩύςΟͷҰ෦Λมߋͯ͠৽͍͠ΦϒδΣΫτΛ࡞Δ͜ͱ͕؆୯ʹʂ • ͜Ε͚ͩͷػೳ͕classͷલʹʮcaseʯ෇͚Δ͚ͩͰوํͷ΋ͷʹʂੜ࢈ੑUPͰϚωʔδϟʔ΋ϗΫϗΫʂ case class People(name:String, birthday:LocalDate) ͨͩ͠ɺcase class͸case classΛܧঝ͢Δ͜ͱ͕Ͱ͖ͳ͍ͷͰ஫ҙ͕ඞཁσε
  11. tuple • ෳ਺ͷσʔλΛ1ͭͷ͔ͨ·Γͱͯ͠ѻ͑Δ • ܕ͕ҟͳΔෳ਺ͷ໭Γ஋Λฦؔ͢਺͕ॻ͚Δʂ • Θ͟Θ͟໭Γ஋༻ͷclassΛఆٛ͠ͳͯ͘΋ࡁΉʂָνϯʂ val pair =

    (99, "NDS#48") pair._1 → 99 pair._2 →”NDS#48" ʮ_1ʯͷΑ͏ʹ ॱ൪Λࢦఆͯ͠ΞΫηεͰ͖Δ val (num, str) = (99, "NDS#48") ม਺ʹ֨ೲ͢Δ͜ͱ΋Ͱ͖Δ →ͬͪ͜ͷํ͕ಡΈ΍͍͢ ͱ͸ݴ͑ɺσʔλ͕ͨ͘͞Μ͋Δ৔߹͸ ໭Γ஋༻ͷclassΛ࡞ͬͨํ͕ݟ௨͕͠ྑ͘ͳΔͱࢥ͏
  12. for͸͍Ζ͍Ζ࢖͑·͢ val strs = Seq("a", "b", "c") for(str <- strs)

    { //ॱ൪ʹstrʹ஋͕ೖͬͯΔ } ͙Δ͙Δ·Θ͢(JavaͰݴ͏֦ுfor) val strs = Seq("a", "b", "c") for((str, index) <- strs.zipWithIndex) { //strʹ͸ཁૉɺindex͸index } JavaͰ͍͏֦ுforͷ index(Կ൪໨ͷཁૉ͔)΋औಘͰ͖·͢ʂ val strs = Seq("a", "b", "", "d") for(str <- strs if str.nonEmpty) { //“a”,”b”,”d”ͷ࣮࣌ߦ͞ΕΔ } ۭจࣈ͡Όͳ͍΍͚ͭͩॲཧର৅ʹ͍ͨ͠ʂ val strs = Seq("a", "b", "c") val newStrs = for(str <- strs) yield { "new:" + str } →newStrs͸৽͘͠࡞ΒΕͨList list͔Β৽͍͠listΛ࡞Γ·͠ΐ͏ (for͕݁ՌΛฦ͠·͢)
  13. match ͸ switch case ͷڧྗ൛ • ஋ʹΑͬͯॲཧΛ෼͚Δ͜ͱ͕Ͱ͖Δ • จࣈྻ΍਺஋ͷൺֱ͸΋ͪΖΜɺܕͰൺֱ͢Δ͜ͱ΋Ͱ͖Δ •

    Α͘ݟΔͷ͸Option͔Β஋Λऔͬͯ͘Δ࣌ s match { case "abc" => 1 case "def" => 2 case _ => 3 } break͸ෆཁ defaultͷcase͸”_” val result = s match { case "abc" => 1 case "def" => 2 case _ => 3 } ஋Λฦ͢͜ͱ΋Ͱ͖Δ n match { case m if m < 0 => "ෛ਺" case 0 => "zero" case m if m <= 3 => "3ҎԼ" case _ => "ͨ͘͞Μ" } ৚݅΋ॻ͚Δ
  14. ໊લ෇͖Ҿ਺ • ίϯετϥΫλ΍ϝιουͷҾ਺ΛఆٛॱͰͳ͘ɺҾ਺໊Ͱࢦఆ͢Δ͜ͱ͕Ͱ͖Δ • Ҿ਺ͷॱ൪ͷมߋʹ΋ڧ͍ • ݺͼग़͠ݩͷهड़͕ཧղ͠΍͍͢ʂ • ಉ͡ܕ͕3ͭ͘Β͍ͷϝιουͩͱ໊લ෇͖Ҿ਺ͷํ͕͏Ε͍͠ʂ •

    ஋͕ࢦఆ͞Ε͍ͯͳ͍࣌Λڐ༰͢Δ࣌͸ɺॳظ஋΋ࢦఆͰ͖Δɻָνϯʂ save(entity, true, false, true) save(isAdmin = true, isParent = false, isRefresh = true, target = entity) ex. ) def save(target:People, isAdmin:Boolean, isParent:Boolean, isRefresh:Boolean) ͲͪΒ΋ݺͼग़ͤΔɻԼͷ΄͏͕Boolean͕ԿΛҙຯ͢Δ͔Θ͔Γ΍͍͢
  15. nullΛฦ͢ઃܭͷฐ֐… /** * idʹඥͮ͘Ϩίʔυ͕ଘࡏͨ͠৔߹ɺͦͷDTO * ଘࡏ͠ͳ͍৔߹ɺnull */ People get(Long id);

    People people = get(id); String name = people.name; nullνΣοΫ͠ͳ͍ͱɺψϧϙ͕ग़Δ͔΋ Կ͔݁ՌΛฦ͢ॲཧΛॻ࣌͘ɺॲཧͰ͖ͳ͔ͬͨ࣌ʹnullΛฦ͢ઃܭͨ͜͠ͱ͸͋Γ·ͤΜ͔ʁ ͦͷΑ͏ͳ৔߹ɺݺͼग़͠ݩͰnullνΣοΫΛ͠ͳ͍ͱ ࣮ߦ࣌ʹNullPointerException͕throw͞ΕΔՄೳੑ͕͋Γ·͢ɻ People people = get(id); String name = “”; if(people != null) { name = people.name } -- java -- ָ؍తͳώτ -- Χλ͘
  16. ͞Α͏ͳΒ NullPointerExceptionʂ /** * idʹඥͮ͘Ϩίʔυ͕ଘࡏͨ͠৔߹ɺSome[People] * ଘࡏ͠ͳ͍৔߹ɺNone */ def get(id:Long):Option[People]

    val peopleOpt = get(id) val name = peopleOpt match { case Some(people) => people.name case None => “” } ScalaͰ͸nullͱܾผ͢ΔͨΊʹʮOptionʯʹ͘ΔΜͰฦ͢͜ͱΛ͠·͢ɻ (Java8͔Β΋OptionalͰ࣮ݱͰ͖·͕͢…) Option͔Β஋ΛऔΓग़͢ॲཧΛߦ͏ͷͰ Noneͷ࣌ͷॲཧΛҙࣝ͠ͳ͚Ε͹ͳΒͳ͍
  17. ༗Δ/ແ͠Ͱͳ͘ɺ΋͏গ͠ৄࡉͳ ৘ใ͕ཉ͍͠৔߹͸Eitherܕ def getInputStream(filePath:String):Either[Exception , FileInputStream] ࣦഊ࣌:Left→ࣦഊͨ͠ཧ༝౳ ੒ޭ࣌:Right ※͜ͷϝιουͷ݁Ռ͸ɺLeft or

    Rightʹ͘ΔΜͰฦ͢ඞཁ͕͋Γ·͢ getInputStream(“hoge.csv”) match { case Left(e) => //͜͜ʹདྷΔͱ͖͸ɺࣦഊ࣌ɻม਺eʹException͕ଋറ͞ΕΔ case Right(is) => //͜͜ʹདྷΔͱ͖͸ɺਖ਼ৗऴྃ࣌ɻม਺inʹFileInputStream͕ଋറ͞ΕΔ } ྫ֎ൃੜ࣌͸ɺ͜Μͳײ͡ʹ͢ΔͷͰɺScalaͰ͸ExceptionΛthrow͢Δػձ͸ݮΓ·͢ try ʙ catchΛॻ͔ͳͯ͘ࡁΉͷͰɺݟͨ໨εοΩϦʂ
  18. OptionΛ࢖͍͸͡ΊΔͱ… 1. AςʔϒϧʹҾ਺ͷid͕߹க͢ΔϨίʔυ͕͋Ε͹࣍ͷॲཧ΁ɺແ͚Ε͹None →funcA 2. ʮ1ʯͷϨίʔυͷதʹސ٬ID͕ઃఆ͞Ε͍ͯΕ͹࣍ͷॲཧ΁ɺແ͚Ε͹None 3. ʮ2ʯͷސ٬IDʹඥͮ͘1೥ؒͷച্Λूܭ͠໭Γ஋ͱͯ͠Optionʹ͘ΔΜͰฦ͢ →funcC Έ͍ͨͳॲཧ͸ɺ

    val result = funcA(id) match { case Some(record) => record.customerId match { case Some(customerId) => funcC(customerId) case _ => None } case _ => None //funcAͷॲཧͰσʔλ͕ແ͔ͬͨ࣌ͷ໭Γ஋ } ؒҧͬͯͳ͍͚Ͳɺωετ͕ଟ͍͠ɺ funcAͷॲཧݺͼग़͠Ͱσʔλ͕͋Δ / ແ͍࣌ͷهड़͕཭ΕͯͯݟͮΒ͍… →ωετ͕͞Βʹਂ͘ͳΔ or தͷॲཧ͕௕͘ͳΔ΄ͲݟͮΒ͘ͳΔ
  19. લఏ৚݅Λશͯຬ͚ͨͨ࣌ͩ͠ ॲཧΛ͍ͨ͠৔߹͸ɺforࣜ val result = for { record <- funcA(id)

    customerId <- record.customerId } yield funcC(customerId) ͦΕͧΕ͕NoneͰͳ͍࣌ʹyieldͷॲཧ͕࣮ߦ͞ΕΔ ม਺resultʹ͸ Option(funcCͷ໭Γ஋) or None͕ઃఆ͞ΕΔ ͘͢͝εοΩϦʂϝϯς͠΍͍͢ʂ
  20. ·ͱΊ • όάͷग़ʹ͍͘ιʔείʔυΛॻͨ͘Ίͷखஈͱͯ͠Scalaͷ࿩Λ͠·ͨ͠ • val Ͱ immutableͳΦϒδΣΫτΛѻ͑ΔΑ͏ʹͳͬͯ͘Δͱɺόάͷग़ʹ ͍͘ιʔείʔυʹͳ͍͖ͬͯ·͢ • ௕͘อक্͍ͯ͘͠Ͱվम͕ॏͳΓɺʮ୭ͩʁ͜͜ʹखΛೖΕౕͨ͸ʁʯ

    ͕ൃੜ͢Δස౓ΛݮΒͤΔͱࢥ͍·͢ • ΋ͪΖΜɺJavaͰ΋lombok࢖͑͹Ͱ͖Δ͔΋͠Ε·ͤΜ͕… • WebΞϓϦͷαʔόαΠυ͸ԿͰ΋ྑ͍΍ɺͱ͍͏͜ͱͰ͋Ε͹ɺෆࣗ༝ ͞ͱҾ͖׵͑ʹܕ҆શͳόάͷग़ʹ͍͘ιʔείʔυɺॻ͍ͯΈ·ͤΜ͔ʁ