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

なぜ Scala 3 で変わったのか / Why things are changed in ...

Avatar for Taisuke Oe Taisuke Oe
January 31, 2020

なぜ Scala 3 で変わったのか / Why things are changed in Scala3?

Scala 3で変わった機能の背景事情と、現段階でわかっているマイグレーションの話中心です。

2020/1/31 (株)セプテーニ・オリジナル 社内勉強会 資料

Avatar for Taisuke Oe

Taisuke Oe

January 31, 2020
Tweet

More Decks by Taisuke Oe

Other Decks in Technology

Transcript

  1. -FBTU6QQFS#PVOE ֓આ w ͬ͘͟Γݴ͑͹ʮෳ਺ͷܕʹڞ௨͢ΔTVQFSUZQFͷ͏ͪɺ࠷΋TVCUZQFʯ w ྫ )PHFͱ'VHBͷMVC͸1SPEVDUXJUI4FSJBMJ[BCMF w 4DBMBYͰ͸MVCͰແݶͷܭࢉ͕ඞཁʹͳΔέʔε͕͋Γɺۙࣅ஋Λ࢖͏ͳͲ ͍ͯ͠Δɻ

    w 4DBMBͰ͸߹ซܕʹΑΓɺ͠͹͠͹༗ݶͷܭࢉͰ͓͞ΊΒΕΔɻ case class Hoge() case class Fuga() val list = List(Hoge(), Fuga()) //Scala 2.13.1 //list: List[Product with java.io.Serializable] = List(Hoge(), Fuga())
  2. MVCܭࢉͰ߹ซܕ͕໾ཱͭ trait C[+T] trait D trait E class A extends

    C[A] with D class B extends C[B] with D with E val list = List(new A(), new B()) //Scala 2.13.1 //list: List[C[C[D] with D] with D] = List(A@456b140f, B@2459333a) //Dotty 0.21.0-RC1 //val list: List[C[A | B] & D] = List(A@2737a1e5, B@7bebb2d0)
  3. w 4DBMB w ༨ஊ ίϯύΠϧ௨Γ·͢ scala> list.head res9: C[C[D] with

    D] with D = A@6e00d737 scala> val a: C[C[D] with D] with D = new A() a: C[C[D] with D] with D = A@10b7b5f0
  4. ަࠩܕ *OUFSTFDUJPOBM5ZQF w "# w "͓Αͼ#ͷTVCUZQF w "##" w "XJUI##XJUI"ͱͳΔέʔε͕͋Δ

    w "XJUI#ܕ DPNQPVOEUZQF Λஔ͖׵͑Δ༧ఆ w OFX FYUFOETʹ͸Ҿ͖ଓ͖࢒Δ
  5. 4DBMBͷߴ֊(FOFSJDT w 4DBMB͸ߴ֊ͷ(FOFSJDTΛαϙʔτ͍ͯ͠Δ w ܕύϥϝʔλʹܕίϯετϥΫλ౉͢৔߹ɺܕίϯετ ϥΫλύϥϝʔλͷ਺͕Ұக͢Δඞཁ͕͋Δɻ w scala> //ߴ֊ͷGenericsɻܕίϯετϥΫλFΛड͚औΔɻ scala>

    class A[F[_]] defined class A scala> //ListΛܕίϯετϥΫλͱͯ͠౉͢ɻ scala> new A[List]() res0: A[List] = A@188b6035 scala> //MapΛܕίϯετϥΫλͱͯ͠౉͢ɻ scala> new A[Map]() ^ error: Map takes two type parameters, expected: one
  6. w 4DBMBͰܕίϯετϥΫλΛఆٛ͢ΔͨΊʹɺຖճUZQFఆٛ͢Δͷ͕৑௕ʜͱ͍͏͜ͱͰੜΈग़͞ΕͨΠ σΟΦϜ w ߏ଄త෦෼ܕʴந৅ܕϝϯόʴܕࣹӨΛར༻͍ͯ͠Δ͕ɺ෼͔Γʹ͍͘ߏจͳͷ͕೉఺ɻ w 4DBMBɺίϯύΠϥϓϥάΠϯͳ͠ w trait MyFunctor[F[_]]{

    def map[T, U](f: F[T])(func: T => U):F[U] } class EitherMyFunctor[L] extends MyFunctor[({ type λ[R] = Either[L, R]})#λ]{ def map[T, U](f: Either[L, T])(func: T => U): Either[L, U] = f match { case Right(r) => Right(func(r)) case Left(l) => Left(l) } } ແ໊ܕίϯετϥΫλ
  7. w UZQFMFWFMLJOEQSPKFDUPS͸ɺܕϥϜμ ͰܕίϯετϥΫλ Λهड़͢ΔͨΊͷίϯύΠϥϓϥάΠϯ w ͜͜Ͱ ͸ɺܕϥϜμͷQMBDFIPMEFSߏจɻ w ࢀߟ஋ϨϕϧͷQMBDFIPMEFSߏจʜ-JTU 

    NBQ G @  w trait MyFunctor[F[_]]{ def map[T, U](f: F[T])(func: T => U):F[U] } class EitherMyFunctor[L] extends MyFunctor[λ[R => Either[L, R]]]{ def map[T, U](f: Either[L, T])(func: T => U): Either[L, U] = f match { case Right(r) => Right(func(r)) case Left(l) => Left(l) } } class AnotherEitherMyFunctor[L] extends MyFunctor[Either[L, *]]{ def map[T, U](f: Either[L, T])(func: T => U): Either[L, U] = f match { case Right(r) => Right(func(r)) case Left(l) => Left(l) } } ,JOEQSPKFDUPS
  8. ܕϥϜμ5ZQF-BNCEB w 4DBMBͰ͸ɺσϑΥϧτͰܕϥϜμ͕αϙʔτ͞ΕΔ w trait MyFunctor[F[_]]{ def map[T, U](f: F[T])(func:

    T => U):F[U] } class EitherMyFunctor[L] extends MyFunctor[[R] =>> Either[L, R]] { def map[T, U](f: Either[L, T])(func: T => U): Either[L, U] = f match { case Right(r) => Right(func(r)) case Left(l) => Left(l) } }
  9. ܕϥϜμ5ZQF-BNCEB w %PUUZ͔ΒɺNJHSBUJPOͷͨΊʹ:LJOEQSPKFDUPSϑϥά ͰLJOEQSPKFDUPSޓ׵ͷQMBDFIPMEFSߏจ͕௥Ճ͞ΕΔɻ w ࢀߟ'JY*NQMFNFOULJOEQSPKFDUPS DPNQBUJCJMJUZ w trait MyFunctor[F[_]]{

    def map[T, U](f: F[T])(func: T => U):F[U] } class EitherMyFunctor[L] extends MyFunctor[Either[L, *]]{ def map[T, U](f: Either[L, T])(func: T => U): Either[L, U] = f match { case Right(r) => Right(func(r)) case Left(l) => Left(l) } }
  10. ϫΠϧυΧʔυܕมߋͷఏҊ w 1SF4*1VTJOHVOEFSTDPSFTGPSUZQFMBNCEBT w 4DBMBYͰ͸ɺΞϯμʔείΞ ྫ'<@> ͸ϫΠϧυΧʔυܕΛද͢ɻ w ܕϥϜμͷQMBDFIPMEFSߏจͰ΋ɺΞϯμʔείΞΛ࢖͍͍ͨ w

    ϫΠϧυΧʔυܕʹׂΓ౰ͯΔه߸Λม͑Ε͹Α͍ͷͰ͸  w +BWBಉ༷ ʹ͢ΔҊ w /* ҎԼͷίʔυ͸·ͩίϯύΠϧ௨Βͳ͍͕ɺ΋࣮͠ݱ͢Δͱ͜͏ͳΔɻ Dotty-0.21.0-RC1ݱࡏͷঢ়گ: - ? ΋ɺϫΠϧυΧʔυܕͱͯ͠࢖͑Δ - _ ΛɺܕϥϜμͷplaceholderߏจͱͯ͠࢖͑ͳ͍ɻ */ trait MyFunctor[F[?]]{ def map[T, U](f: F[T])(func: T => U):F[U] } class EitherMyFunctor[L] extends MyFunctor[Either[L, _]]{ def map[T, U](f: Either[L, T])(func: T => U): Either[L, U] = f match { case Right(r) => Right(func(r)) case Left(l) => Left(l) } }
  11. ϫΠϧυΧʔυܕมߋͷಓఔ w ΋࣮͠ݱ͢ΔͱɺΞϯμʔείΞ@ͷར༻৔ॴ͕ಉ͡Ͱɺ༻్͚ͩมΘΔɻ w ιʔεͷޓ׵ੑΛഁյ͢Δɻ w ౓ͷมߋͰࡁ·ͳ͍ w ௕ظʹΘͨΔNJHSBUJPOϓϥϯ͕ఏҊ͞Ε͍ͯΔʢ͕ɺ·ͨະ֬ఆ 

    w 4DBMBYLJOEQSPKFDUPSʜܕϥϜμQMBDFIPMEFSΛ ͔Β ΁มߋ ࡁ  w 4DBMBʜ@ͱ ΛϫΠϧυΧʔυܕͱͯ͠ڐ༰ @͸TUSJDUͰඇਪ঑ ΠϚίί w 4DBMBʜϫΠϧυΧʔυܕͱͯ͠ͷ@ར༻Λඇਪ঑ w 4DBMBʜϫΠϧυΧʔυܕͱͯ͠ͷ@Λ࡟আ w 4DBMBʜܕϥϜμͷQMBDFIPMEFSͱͯ͠@Λ௥Ճ
  12. ܧঝΑΓ߹੒ w &⒎FDUJWF+BWBOEFEJUJPOΑΓҾ༻ w *UFN'BWPSDPNQPTJUJPOPWFSJOIFSJUBODF w 6OMJLFNFUIPEJOWPDBUJPO JOIFSJUBODFWJPMBUFTFODBQTVMBUJPO w *UFN%FTJHOBOEEPDVNFOUGPSJOIFSJUBODFPSFMTFQSPIJCJUJU

    w ܧঝͰTVQFSUZQFͷ࣮૷Λमਖ਼͢ΔͱɺͦͷΧϓηϧԽΛഁյ͢ΔՄೳੑ͕͋Δɻ w ܧঝ͢Δඞཁ͕ͳ͍ݶΓɺ߹੒ͱϝιουݺͼग़͠Λར༻͢Δ΂͠ɻ w ܧঝ͍ͤͨ͞ΫϥεΛ໌ࣔ͠ɺద੾ʹઃܭ͢Δɻͦͷ΄͔͸ܧঝΛආ͚Δɻ
  13. 0QFO //openclass.scala package p open class PleaseExtendMe { def hello(name:

    String): String = s"Hello, ${name}!" } class DontWantToExtendMe { def hello(name: String): String = s"Hello, ${name}!" } //subtype.scala package p class A extends PleaseExtendMe { override def hello(name: String): String = super.hello(name) + " " } class B extends DontWantToExtendMe { override def hello(name: String): String = super.hello(name) + " "
  14. 0QFO w EPUDTUSJDU w [warn] -- Feature Warning: /Users/{my path}/DottySandbox/src/main/scala/oop/subtype.scala:

    7:16 [warn] 7 |class B extends DontWantToExtendMe { [warn] | ^^^^^^^^^^^^^^^^^^ [warn] |Unless class DontWantToExtendMe is declared 'open', its extension in a separate file should be enabled [warn] |by adding the import clause 'import scala.language.adhocExtensions' [warn] |or by setting the compiler option -language:adhocExtensions. [warn] |See the Scala docs for value scala.language.adhocExtensions for a discussion [warn] |why the feature should be explicitly enabled.
  15. ܧঝؔ࿈ͷम০ࢠ੔ཧ w ಉҰιʔεϑΝΠϧ֎͔ΒͷܧঝΛ૝ఆ w PQFODMBTT w BCTUSBDUDMBTT w USBJU w

    ಉҰιʔεϑΝΠϧ֎͔Βͷܧঝ΋Մೳ ܯࠂ  w DMBTT w ಉҰιʔεϑΝΠϧ֎͔ΒͷܧঝΛېࢭ ίϯύΠϧΤϥʔ  w TFBMFE w ܧঝΛېࢭ w pOBM
  16. &YQPSU w ҕৡΛ؆ศʹ͢Δػೳ w ͋ΔΦϒδΣΫτΛFYQPSU͢ΔͱɺΤΠϦΞεͷϝϯόʔ͕ࣗ ಈతʹ௥Ճ͞ΕΔ w class DontWantToExtendMe {

    def hello(name: String): String = s"Hello, ${name}!" } class Wrapper(dont: DontWantToExtendMe) { export dont._ // ্هͷexport͸ɺҎԼͱ౳Ձ // def hello(name: String): String = dont.hello(name) } val wrapper = new Wrapper(new DontWantToExtendMe()) println(wrapper.hello("world"))
  17. &YQPSU w FYQPSUͰɺଞͷϝϯόͱিಥ͢ΔͱίϯύΠϧΤϥʔ w class DontWantToExtendMe { def hello(name: String):

    String = s"Hello, ${name}!" } class Wrapper(dont: DontWantToExtendMe) { export dont._ def hello(name: String): String = s"Hello, ${name} from wrapper!" } [error] -- [E120] Duplicate Symbol Error: /Users/{my_path}/DottySandbox/src/main/scala/oop/ OpenClass.scala:13:16 [error] 13 | export dont._ [error] | ^ [error] | Double definition: [error] | def hello(name: String): String in class Wrapper at line 14 and [error] | final def hello(name: String): String in class Wrapper at line 13 [error] | have the same type after erasure. [error] one error found
  18. 4DBMBͷόΠφϦޓ׵ੑ w 4DBMB͔Βɺ4DBMBͷʢϚΫϩҎ֎ͷʣόΠφϦΛར༻ Ͱ͖Δ w কདྷతʹɺ4DBMBͷόΠφϦ 5"45Z Λ4DBMB͔Β ར༻Ͱ͖ΔΑ͏ʹ͢Δ༧ఆ ࢀߟ

     w ͞Βʹ4DBMBYܥͰ͸ɺ5"45ZʹΑΓόΠφϦޓ׵ੑ͕ҡ࣋ ͞ΕΔΒ͍͠  ʜࢀߟ w ඪ४ϥΠϒϥϦ JFίϨΫγϣϯ ͸4DBMBͰมߋͳ͠ w 4DBMBͷඪ४ϥΠϒϥϦΛར༻͢Δ
  19. 4DBMBͷϚΫϩͷޓ׵ੑ w 5IF3PBE5P4DBMB8IBUBCPVUNBDSP  w ൈਮ5IFNBDSPTZTUFNGSPN4DBMBJTEFFQMZ UJFEUPUIFJOUFSOBMTPGUIF4DBMBDPNQJMFSBOE DBOOPUCFNJHSBUFEJOBDPNQBUJCMFGBTIJPOUP 4DBMB w

    ϚΫϩΛར༻͍ͯ͠ΔϥΠϒϥϦ͸ɺ4DBMB޲͚ʹॻ ͖׵͕͑ඞཁɻॻ͖׵͑πʔϧ౳ͷิॿ͸͓ͦΒ͘ͳ ͍ɻ 4DBMBίϯύΠϥͱͷີ݁߹ͷ͍ͤͰͰ͖ͳ͍
  20. ϚΠάϨʔγϣϯ w 4DBMBpYͷ׆༻͕த৺ͱͳΔ༧ఆ w 4DBMBҠߦͷͨΊʹ։ൃ͕࢝·ͬͨɺ੩తղੳʹΑΔ 3FXSJUFπʔϧ w 4DBMBpYࣗମ͸ɺ͞·͟ͳϓϩδΣΫτͰϓϩμΫγϣϯ౤ೖ ͞Ε͍ͯΔ w

    4DBMBpY༻ͷ4DBMBSFXSJUFSVMF͸ɺ·ͩ͋·Γ࣮૷͞Εͯ ͍ͳ͍ ࣌఺  w 4DBMB$FOUFSओମͰɺSFXSJUFSVMFͷ࣮૷ʹऔΓ૊Ή༧ఆ
  21. ϥΠϒϥϦϝϯςφ͕ ࠓऔΓ૊ΜͰ͍Δ͜ͱ w ࢼݧతʹEPUUZରԠΛ͸͡Ί͍ͯΔਓ͕ͪΒ΄Β͍·͢ଟँ w $BUT $JSDFͷϚΫϩҎ֎͸େৎ෉ͦ͏ w 4DBMJLF+%#$DPSF ϚΫϩͳ͠

    ͸େৎ෉ͦ͏  w .6OJU͸%PUUZ.BDSPʹରԠɺϦϦʔε͍ͯ͠Δ w ௥ه 044BOE1SPGFTTJPOBMUIPVHIUTPONJHSBUJOHUP4DBMB w $SPTTCVJME༻ͷόʔδϣϯґଘιʔεͰॏෳίʔυ͕૿͑ͦ͏ɺͳ Ͳͷݒ೦Λද໌͍ͯ͠Δ
  22. w 5IFCJHHFTUUIJOH4DBMBOFFETGSPNUIFDPNNVOJUZJTGPS FWFSZPOFUPCFHJOQPSUJOHUIFJSDPEF w ʮͥͻ4DBMBΛΈͳ͞ΜͷϓϩδΣΫτͰࢼ͍ͯͩ͘͠͞ʂʯ w ͨͩ·ͩ4DBMBϚΫϩʹରԠͯ͠ΔϥΠϒϥϦ͕গͳ͍ɻ ґଘϥΠ ϒϥϦؚΊ ϚΫϩΛ࢖ͬͯͳ͍ϓϩδΣΫτ͡Όͳ͍ͱݫͦ͠

    ͏ʜʜ  w ۀ຿ίʔυͰ4DBMBΛࢼͤΔͷ͸ɺ΋͏গ͠ޙʹͳΓͦ͏ɻ w ۀ຿ίʔυͷຊ֨4DBMBରԠ͸ɺ۩ମతͳϚΠάϨʔγϣϯͷ৘ใ͕ ग़͔ͯΒͰ΋஗͘ͳ͍ɻ ɹۀ຿4DBMBϢʔβ͕ ɹɹɹɹɹɹࠓͰ͖Δ͜ͱɹɹɹ