Martinã¯ãã®ããŒãã«ã€ããŠäœåºŠã話ãããŸããããããã§Dottyã«é¢é£ãããã¹ãŠã®æ å ±ãåéããããšæããŸããäžèŠãªãã®ãšããŠåé€ãããæ°ããéèŠãªæ©èœãšèŠçŽ ã§ãã
ããŒãã£ã³ã»ãªãŒãã«ã¹ããŒã ä»åŸæ°å¹Žéã®Scalaéçºèšç»
ãã®æçš¿ã¯å°é家ãšåå¿è ã®äž¡æ¹ã«åœ¹ç«ã¡ãŸããç§ã¯Dottyã«ã€ããŠã®äŒè©±ã®åã«ãScalaã®æ©èœã«ã€ããŠã®è©±ãšæ°åŠçãªåºç€ã«ããããšã«ã€ããŠè©±ãããŸãã
Scalaã¯ãã«ããã©ãã€ã ããã°ã©ãã³ã°èšèªã§ãå ã ã¯JVMïŒJavaä»®æ³ãã·ã³ïŒã®äžã§éçºãããŸããã ãããçŸåšãJavaScriptïŒScalaJSïŒããã³ãã€ãã£ãã³ãŒãïŒScalaãã€ãã£ãïŒã®ç¿»èš³è ãéçºãããŠããŸãã Scalaãšããååã¯ãã¹ã±ãŒã©ãã«èšèªïŒãã¹ã±ãŒã©ãã«èšèªãïŒã«ç±æ¥ããŸãã å®éãScalaã§ã€ã³ã¿ãŒããªã¿ãŒã§å®è¡ã§ããããã€ãã®è¡ã®å°ããªã¹ã¯ãªããïŒread-eval-print loopãREPLïŒãšãå€æ°ã®ãã·ã³ã®ã¯ã©ã¹ã¿ãŒã§å®è¡ãããè€éãªã·ã¹ãã ïŒç¹ã«ã akkaããã³Apache sparkãã¬ãŒã ã¯ãŒã¯ã䜿çšïŒã
ScalaãéçºããåãMartin Oderskyã¯Javaã®ãžã§ããªãã¯åã®éçºã«é¢äžããŠããŸãããããã¯2004幎ã«Java 5ã«ç»å ŽããŸããã ã»ãŒåææã«ãMartinã¯JVMçšã®æ°ããèšèªãäœæãããšããã¢ã€ãã¢ãæãä»ããŸãããããã«ã¯ãåœæã®Javaã«ãã£ã倧ããªåŸæ¹äºææ§ããããŸããã Martinãèšç»ããããã«ãæ°ããèšèªã¯ãJavaã®ãªããžã§ã¯ãæåã¢ãããŒããšHaskellãOCamlãErlangèšèªã§äœ¿çšãããŠããã®ãšåæ§ã®æ©èœçã¢ãããŒããçµã¿åãããåæã«åŒ·ãåä»ããããèšèªã§ããã
匷ãåä»ããããèšèªãšããŠã®Scalaã®äž»ãªæ©èœã®1ã€ã¯ãèªååæšè«ã®ãµããŒãã§ãã åŒããšã«åãæ瀺çã«æå®ããå¿ èŠãããä»ã®åä»ãèšèªãšã¯ç°ãªããScalaã§ã¯ãå€æ°ã®åãšé¢æ°ã®æ»ãå€ã®åãæé»çã«æ±ºå®ã§ããŸãã ããšãã°ãJavaã®å®æ°å®çŸ©ã¯æ¬¡ã®ããã«ãªããŸãã
final String s = "Hello world";
ããã¯ãScalaã®æ¬¡ã®åŒãšåçã§ãã
val s = "Hello world"
ãã ããScalaã§ã¯ãããšãã°ãå€æ°ãæå®ãããåŒã®ã¹ãŒããŒã¿ã€ãã§ããåãæããªããã°ãªããªãå Žåãªã©ãåŒã®åãæ瀺çã«æå®ããããšãã§ããŸãã
val cs: CharSequence = "Hello world"
Martin Oderskyã¯ãæé»çãªåæšè«ã®èŠåããä»ã®èšèªãšåºå¥ããèšèªã®äž»èŠãªç¹åŸŽã§ãããšèããŠããŸãã çŸåšã圌ã¯ãã®ã·ã¹ãã ã®æ¹åãšãDOT埮ç©åïŒDOT埮ç©åïŒãšåŒã°ããæ°åŠçåºç€ã®ç 究ãææ®ããŠããŸãã
ãããèšç®
DOTã¯äŸåãªããžã§ã¯ãã¿ã€ããã€ãŸã äŸåãªããžã§ã¯ãã®ã¿ã€ããæšæž¬ããŸãã äŸååãšã¯ãç¹å®ã®æäœã®çµæãšããŠååŸãããåã§ãã èšèªã®çŸåšã®ããŒãžã§ã³ã§ã¯ãæ¢åã®ãã®ã«åºã¥ããŠåãå°åºããããã®ç¹å®ã®ã«ãŒã«ã»ãããæ¢ã«ãããŸããããšãã°ãäžãŸãã¯äžããã®ç¶æ¿éå±€ã®å¶éããŸãã¯åŒæ°ã«å¿ããåæšè«ïŒãã¹äŸååïŒã§ãã 以äžã«å°ããªäŸã瀺ããŸãã
trait A { type B def someFunction(b: B): B } trait C[X <: D] { type Y = (X, D) def fun1(x: X): Y def fun2(a: A): aB }
ãã®äŸã§ã¯ãAãšCã®2ã€ã®ç¹æ§ãå®çŸ©ããŸããç¹æ§Aã«ã¯ã¿ã€ããã£ãŒã«ãBããããã¿ã€ãBå ¥åãåãåãsomeFunctioné¢æ°ãå®çŸ©ããŸããã¿ã€ãBã®å€ã¯ãAã®ç¹å®ã®å®è£ ã«å¿ããŠæ±ºãŸããŸããåãã©ã¡ãŒã¿ãŒXã¯ãåDã®åå«ã§ãªããã°ãªããŸãããç¹æ§Cã¯ãåãã£ãŒã«ãYãšã2ã€ã®é¢æ°fun1ããã³fun2ãå®çŸ©ããŸãã fun1ã¯ã¿ã€ãXã®å ¥åãåãå ¥ããã¿ã€ãYã®å€ãè¿ããŸããfun2ã¯ã¿ã€ãAã®å€ãåãå ¥ããŸãããæ»ãå€ã®ã¿ã€ãã¯åŒæ°Aã®ã¿ã€ããã£ãŒã«ãBã®å€ã«ãã£ãŠæ±ºãŸããŸãã
DOTèšç®ã¯ããã®ãããªå°åºã®èŠåã®æ°åŠç圢åŒåã§ãã DOTèšç®ã®äž»ãªèŠçŽ ïŒ
- æäžäœã¿ã€ãïŒä»»æïŒ-éå±€ã®æäžäœã®ã¿ã€ãã¯ããã¹ãŠã®ã¿ã€ãã®ã¹ãŒããŒã¯ã©ã¹ã§ãã
- ããã ã¿ã€ãïŒãªãïŒ-éå±€ã®äžã®ã¿ã€ãã¯ããã¹ãŠã®ã¿ã€ãã®ãµãã¿ã€ãã§ãã
- å宣èš-æå®ãããå¢çã®äžäžã®å宣èšã
- ã¿ã€ãã®éžæ-å€æ°ã«å¿ããã¿ã€ãã®æšè«ã
- é¢æ°-å
¥åãšããŠããŸããŸãªã¿ã€ãã®1ã€ä»¥äžã®åŒæ°ãåããç¹å®ã®ã¿ã€ãã®å€ãæã€é¢æ°ã
ããã«ãDOTèšç®ã§ã¯ã次ã®äžé£ã®æå¹ãªåæäœãå®çŸ©ãããŠããŸãã
- ç¶æ¿ å¢çç·ïŒãã®äŸã§ã¯ãAny and NothingïŒã§ãªãå Žåãä»»æã®ã¿ã€ãã¯ãã¹ãŒããŒã¿ã€ããŸãã¯å¥ã®ã¿ã€ãã®ãµãã¿ã€ãã®ããããã§ãã åã¿ã€ãã¯ããèªäœã®ã¹ãŒããŒã¿ã€ãããã³ãµãã¿ã€ãã§ãã
- ä»ã®ã¿ã€ãïŒå€æ°ã®ãªããžã§ã¯ãããã³æ§é ã«é¡äŒŒïŒãå«ãæ§é ã¿ã€ãïŒã¬ã³ãŒãïŒã®äœæã
- åã®çµåã çµæã®åã¯ãå
ã®åã®ãã£ãŒã«ããšæäœã®åé¢ã§ãã
- ã¿ã€ãã®äº€å·®ã çµæã®åã¯ãå
ã®åã®ãã£ãŒã«ããšæäœã®çµã¿åããã«ãªããŸãã
- åã®ååž°çãªå®çŸ©ã
DOTã®è©³çŽ°ãªèª¬æã¯ããã®åºçç©ã®ç¯å²å€ã§ãã DOTèšç®ã«é¢ãã詳现ã¯ã ãã¡ããã芧ãã ãã ã
Dottyã€ãããŒã·ã§ã³ã®æŠèŠ
DOTèšç®ã¯ãDottyã³ã³ãã€ã©ãŒã®æ°åŠçãªåºç€ã§ãã å®éãããã¯ãã®ååã«åæ ãããŠããŸãã
Dottyã¯ãæ°ããèšèªã®æŠå¿µãšã³ã³ãã€ã«æè¡ããã¹ãããããã®å®éšçãªãã©ãããã©ãŒã ã«ãªããŸããã Martin Oderskyã«ããã°ãDottyã®éçºã®ç®æšã¯ãåºæ¬çãªæ§é ã匷åããèšèªã®äžèŠãªèŠçŽ ãåãé€ãããšã§ãã Dottyã¯çŸåšãç¬ç«ãããããžã§ã¯ããšããŠéçºãããŠããŸããããããŠã¡ã€ã³ã®Scalaãã©ã³ãã«çµ±åãããäºå®ã§ãã
é©æ°ã®å®å šãªãªã¹ãã¯ãDottyã®å ¬åŒWebãµã€ãã§èŠã€ããããšãã§ããŸãã ãããŠããã®èšäºã§ã¯ãDottyã§æãéèŠã ãšèããã€ãããŒã·ã§ã³ã®ã¿ãæ€èšããŸãã
1.亀差ç¹ãå ¥åããŸã
åã®äº€å·®ã¯ãå ã®åã®ãã¹ãŠã®ããããã£ãåæã«æã€åãšããŠå®çŸ©ãããŸãã ç¹å®ã®ã¿ã€ãAããã³Bãå®çŸ©ãããšããŸãã
trait A { def fun1(): Int } trait B { def fun2(): String }
ã¿ã€ãCã¯ãã¿ã€ãAãšBã®å ±ééšåãšããŠå®çŸ©ãããŸãã
type C = A & B
ãã®å Žåã次ã®é¢æ°ãèšè¿°ã§ããŸãã
def fun3(c: C): String = s"${c.fun1()} - ${c.fun2()}"
äŸãããããããã«ããã©ã¡ãŒã¿ãŒcã«ã€ããŠã¯ãã¿ã€ãAã«å¯ŸããŠå®çŸ©ãããfun1ïŒïŒã¡ãœãããšã¿ã€ãBã«å¯ŸããŠå®çŸ©ãããfun2ïŒïŒã¡ãœããã®äž¡æ¹ãåŒã³åºãããšãã§ããŸãã
ã³ã³ãã€ã©ã®çŸåšã®ããŒãžã§ã³ã§ã¯ããã®æ©èœã¯withæ§æãä»ããŠãµããŒããããŠããŸããäŸïŒ
type C = A with B def fun3(c: C): String = s"${c.fun1()} - ${c.fun2()}"
ïŒæ§æãšwithæ§æã«ã¯å€§ããªéãããããŸããïŒã¯å¯ææŒç®ã§ããã€ãŸããã¿ã€ãAïŒBã¯ã¿ã€ãBïŒAãšåçã§ãããBãšAã¯BãšAãšåçã§ã¯ãããŸããã以äžã«äŸã瀺ããŸãã
trait A { type T = Int } trait B { type T = String }
ã¿ã€ãAãšBã®å Žåãã¿ã€ãTã®å€ã¯Intã§ããããã¯ãAãBããåªå ãããããã§ããDottyã§ã¯ãã¿ã€ãAãšBã®å Žåãã¿ã€ãTã¯IntïŒStringã«ãªããŸãã
åã®withã³ã³ã¹ãã©ã¯ãã¯Dottyã§åŒãç¶ããµããŒããããŠããŸãããéæšå¥šãšããŠå®£èšãããŠãããå°æ¥åé€ããäºå®ã§ãã
2.ã¿ã€ãunion
åã®åéåã¯ãå ã®åã®ããããã®ããããã£ãæã€åãšããŠå®çŸ©ãããŸãã åã®å ±ééšåãšã¯ç°ãªããçŸåšã®ããŒãžã§ã³ã®scalaã³ã³ãã€ã©ã«ã¯ãåãçµåããããã®é¡äŒŒæ§ããããŸããã çµ±äžãããåãæã€å€ã®å Žåãæšæºã©ã€ãã©ãªã«ã¯å[AãB]ããããŸãã 次ã®ã¿ã€ããå®çŸ©ãããŠãããšããŸãïŒ
case class Person(name: String, surname: String) case class User(nickname: String)
ãã®å Žåã次ã®é¢æ°ãèšè¿°ã§ããŸãã
def greeting(somebody: Person | User) = somebody match { case Person(name, surname) => s"Hello, $name $surname" case User(nickname) => s"Hello $nickname, (sorry, I actually don't know your real name)" }
åçµåã¯ãçŸåšã®ããŒãžã§ã³ã®èšèªã§ããããã䜿çšããå Žåãšæ¯èŒããŠãããçãè¡šèšæ³ãæäŸããŸãã
def greeting(somebody: Either[Person, User]) = somebody match { case Left(Person(name, surname)) => s"Hello, $name $surname" case Right(User(nickname)) => s"Hello $nickname, (sorry, I actually don't know your real name)" }
亀差ã®ãããªåçµåãå¯ææŒç®ã§ãã
åå ±çšäœã®1ã€ã®äœ¿çšäŸã¯ãnullæ§é ãå®å šã«åãé€ãããšã§ãã çŸåšãnullã䜿çšãã代ããã«ãOptionæ§é ã䜿çšãããŸãããããã¯ã©ãããŒãšããŠå®è£ ãããŠãããããè¿œå ã®ãããã³ã°ããã³ã¢ã³ãããã³ã°æäœãå¿ èŠãªãããããã¯ãããã«é ããªããŸãã åéçŽã䜿çšãããšã解決ã¯ã³ã³ãã€ã«æ®µéã§è¡ãããŸãã
def methodWithOption(s: Option[String]) = s match { case Some(string) => println(string) case None => println("There's nothing to print") } type String? = String | Null def methodWithUnion(s: String?) = s match { case string: String => println(string) case Null => println("There's nothing to print") }
3.æãè¿ããµãã¿ã€ããšã¹ãŒããŒã¿ã€ãã®æ±ºå®
ãŠããªã³ãã€ã³ã¿ãŒã»ã¯ã·ã§ã³ãªã©ã®è€ååã«å¯Ÿããæ°ããæäœã®å°å ¥ã«ãããç¶æ¿éå±€ã§æãè¿ãåãèšç®ããããã®ã«ãŒã«ãå€æŽãããŸããã Dottyã¯ããã¹ãŠã®ã¿ã€ãTããã³Uã«ã€ããŠãæãè¿ãã¹ãŒããŒã¿ã€ãã¯T | Uãããã³æãè¿ããµãã¿ã€ãã¯TïŒUã«ãªããŸãããããã£ãŠããããããµãã¿ã€ãã³ã°ã©ãã£ã¹ã圢æãããŸãã 圌女ã¯äžã®å³ã«ããŸãã
çŸåšã®Scalaå®è£ ã§ã¯ãæãè¿ãã¹ãŒããŒã¿ã€ãã2ã€ã®ã¿ã€ãã®å ±éã¹ãŒããŒã¿ã€ããšããŠå®çŸ©ãããŠããŸãã ãããã£ãŠãäžè¬ã«ã2ã€ã®ã±ãŒã¹ã¯ã©ã¹Tããã³Uã®å Žåãæãè¿ãã¹ãŒããŒã¿ã€ãã¯Serializableã®è£œåã«ãªããŸãã Dottyã§ã¯ãããã¯T | TãšããŠäžæã«å®çŸ©ãããŸãã U.
çŸåšã®Scalaå®è£ ã§æãè¿ããµãã¿ã€ãã®å Žåãåäžã®çãã¯ãããŸããã æãè¿ããµãã¿ã€ãã¯ãUãå«ãTãŸãã¯Tãå«ãUã®ããããã§ããåè¿°ã®ããã«ãwithæäœã¯å¯æã§ã¯ãããŸããããããã£ãŠãUãå«ãã¿ã€ãTã¯Tãå«ãã¿ã€ãUãšåçã§ã¯ãããŸãããDottyã¯ãæãè¿ããµãã¿ã€ããTïŒ U.æäœïŒã¯å¯æã§ãããããæå³ã¯äžæã§ãã
val s = "String" val i = 10 val result = if (true) s else i
Scala 2.12ã§ã¯ãçµæã®å€ã«ã¯Anyåãå²ãåœãŠãããŸãã Dottyã§ã¯ãçµæã®ã¿ã€ããæ瀺çã«æå®ããªãéããã¿ã€ãAnyãå²ãåœãŠãããŸãã ãã ããçµæã®ã¿ã€ããæ瀺çã«æå®ã§ããŸãã
val result: String | Int = if (true) s else i
ãããã£ãŠãçµæã®æå¹ãªå€ã®ã»ãããStringåãšIntåã«å¶éããŸããã
4.åã®ã©ã ãåŒ
Scalaã®æãè€éãªèšèªæ©èœã®1ã€ã¯ãããããé«æ¬¡åã®ãµããŒãã§ãã é«éåã®æ¬è³ªã¯ãäžè¬åãããããã°ã©ãã³ã°ã䜿çšãããšãã«æœè±¡åã®ã¬ãã«ãããã«é«ããããšã§ãã é«æ¬¡ã¿ã€ãã®è©³çŽ°ã«ã€ããŠã¯ã ãã®èšäºã§èª¬æããŸã ã Dean WamplerãšAlex PayneïŒç¬¬2çïŒã®èæžProgramming ScalaããåŒçšããç¹å®ã®äŸãæ€èšããŸãã
trait Functor[A, +M[_]] { def map2[B](f: A => B): M[B] } implicit class SeqFunctor[A](seq: Seq[A]) extends Functor[A, Seq] { override def map2[B](f: (A) => B): Seq[B] = seq map f } implicit class OptionFunctor[A](opt: Option[A]) extends Functor[A, Option] { override def map2[B](f: (A) => B): Option[B] = opt map f }
ããã§ã¯ãå€åAãšã©ãããŒMã®åãšãã2ã€ã®åã«ãã£ãŠãã©ã¡ãŒã¿ãŒåãããFunctoråãäœæããŸããScalaã§ã¯ãåŒMïŒãã©ã¡ãŒã¿ãŒãªãïŒã¯åã³ã³ã¹ãã©ã¯ã¿ãŒãšåŒã°ããŸãã æ°ãããªããžã§ã¯ããäœæããããã«ç¹å®ã®ãã©ã¡ãŒã¿ãŒã»ãããååŸã§ãããªããžã§ã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒãšã®é¡æšã«ãããåã³ã³ã¹ãã©ã¯ã¿ãŒã¯ç¹å®ã®åãå®çŸ©ããããã«ãã©ã¡ãŒã¿ãŒãååŸããããšãã§ããŸãã ãããã£ãŠããã®äŸããFunctorã®ç¹å®ã®ã¿ã€ããå€å¥ããã«ã¯ãããã€ãã®ã¹ããããå®äºããå¿ èŠããããŸãã
- ã¿ã€ãã¯ãAããã³Bã«å¯ŸããŠæ±ºå®ãããŸãã
- M [A]ããã³M [B]ã®ã¿ã€ãã決å®ãããŸãã
- Functorã®ã¿ã€ããå®çŸ©ããŸã[AãM]
ãããã£ãŠãã³ã³ãã€ã©ã¯3åç®ã®å埩åŸã«ã®ã¿Functorã®åã決å®ã§ãããããé«æ¬¡åãšèŠãªãããŸãã äžè¬çãªå Žåãé«æ¬¡ã®åã¯ãåçŽåãšåã³ã³ã¹ãã©ã¯ã¿ãŒã®äž¡æ¹ããã©ã¡ãŒã¿ãŒãšããŠåãå ¥ããåã§ãã
äžèšã®äŸã«ã¯1ã€ã®æ¬ ç¹ããããŸããFunctoråã®ãã©ã¡ãŒã¿ãŒã§ã¯ãMåã®ã³ã³ã¹ãã©ã¯ã¿ãŒã¯1ã€ã®ãã©ã¡ãŒã¿ãŒãåãåããŸãã ããŒãå€æŽããã«ãMap [KãV]ã®å€ãå€æŽããmap2ã¡ãœãããèšè¿°ããå¿ èŠããããšããŸãã Dean Wamplerã¯åœŒã®æ¬ã®äžã§æ¬¡ã®è§£æ±ºçãæäŸããŠããŸãã
implicit class MapFunctor[K,V1](mapKV1: Map[K,V1]) extends Functor[V1,({type λ[α] = Map[K,α]})#λ] { def map2[V2](f: V1 => V2): Map[K,V2] = mapKV1 map { case (k,v) => (k,f(v)) } }
ãã®äŸã§ã¯ã1ã€ã®ãã©ã¡ãŒã¿ãŒãåããMapã®æåã®ãã©ã¡ãŒã¿ãŒKãéãããã¿ã€ãλã®æ°ããã³ã³ã¹ãã©ã¯ã¿ãŒãäœæããŸãã ãã®å®è£ ã¯éåžžã«çŽããããã§ãããªããªããã¿ã€ãλã®ã³ã³ã¹ãã©ã¯ã¿ãŒãäœæããããã«ãæ§é ã¿ã€ã{typeλ[α] = Map [Kãα]}ãæåã«äœæããŸããåã®æ圱ã¡ã«ããºã ïŒDottyã¯ãããåãé€ãããšã«ããŸããïŒãä»ããŠã
ãã®ãããªå Žåã®ããã«ãDottyã¯åã®ã©ã ãåŒã®ã¡ã«ããºã ãéçºããŸããã æ§æã¯æ¬¡ã®ãšããã§ãã
[X] => Map[K, X]
ãã®åŒã¯ã1ã€ã®ãã©ã¡ãŒã¿ãŒãæã€ã¿ã€ããšããŠèªã¿åãããŸããããã¯ããããã¿ã€ããæ§ç¯ããŸããããŒã¿ã€ãKã¯ä»»æã§ãå€ã®ã¿ã€ãã¯ãã©ã¡ãŒã¿ãŒãšçãããªããŸãã ãããã£ãŠã次ã®ããã«Mapã®å€ãæäœããFunctorãäœæã§ããŸãã
implicit class MapFunctor[K,V1](mapKV1: Map[K,V1]) extends Functor[V1, [X] => Map[K,X]] { def map2[V2](f: V1 => V2): Map[K,V2] = mapKV1 map { case (k,v) => (k,f(v)) } }
ãã®äŸãããããããã«ãDottyã§å°å ¥ãããåã®ã©ã ãåŒã®æ§æã䜿çšãããšãMapFunctorã¯ã©ã¹ã®å®çŸ©ãç°¡çŽ åããŠãæ··ä¹±ãããã¹ãŠã®æ§é ãåãé€ãããšãã§ããŸãã
åã®ã©ã ãåŒã䜿çšãããšãåŒæ°ã®å ±åæ£ããã³ååæ£ã«å¶çŽã課ãããšãã§ããŸãã次ã«äŸã瀺ããŸãã
[+ XãY] =>ããã[YãX]
5.ã¿ãã«ã«å¯Ÿããé¢æ°ã®ã¢ãªãã£ã®é©å¿æ§
ãã®ã€ãããŒã·ã§ã³ã¯ãã¿ãã«ããã®ã³ã¬ã¯ã·ã§ã³ã®æäœãåçŽåããæ§æç³è¡£ã§ãããProductã¯ã©ã¹ã®ãã¹ãŠã®å®è£ ã§ã®äžè¬çãªã±ãŒã¹ïŒãããã¯ãã¹ãŠã±ãŒã¹ã¯ã©ã¹ã§ãïŒãšåæ§ã§ãã
val pairsList: List[(Int, Int)] = List((1,2), (3,4))
case class Rectangle(width: Int, height: Int) val rectangles: List[Rectangle] = List(Rectangle(1,2), Rectangle(3,4))
ãã®çš®é¡ã®ã³ã¬ã¯ã·ã§ã³ãæäœããããã«ã1ã€ã®åŒæ°ãæã€ããããã®é¢æ°ã䜿çšã§ããŸãã
val sums = pairsLIst.map(pair => pair._1 + pair_2) val areas = rectangles.map(r => r.width * r.height)
ãŸãã¯ãéšåé¢æ°ã䜿çšã§ããŸãã
val sums = pairsLIst.map { case (a, b) => a + b } val areas = rectangles.map { case Rectangle(w, h) => w * h }
Dottyã¯ãããã³ã³ãã¯ãã§äŸ¿å©ãªãªãã·ã§ã³ãæäŸããŸãã
val sums = pairsLIst.map(_ + _) val areas = rectangles.map(_ * _)
ãããã£ãŠãã¿ã€ãProduct Dottyã®ãµãã¯ã©ã¹ã§ã¯ãã¢ãªãã£ãå ã®è£œåã®ã¢ãªãã£ãšçããé¢æ°ãéžæããŸãã
6.ç¹æ§ã®ãã©ã¡ãŒã¿ãŒ
Dottyã¯ãç¹æ§ãå®çŸ©ãããšãã«ãã©ã¡ãŒã¿ãŒãèšå®ããæ©èœãæçµçã«è¿œå ããŸããã ããã¯ãè€éãªç¶æ¿éå±€ã®å Žåããã©ã¡ãŒã¿ãŒå€ãæªå®çŸ©ã§ãã£ããšããäºå®ã«ããããããŸã§è¡ãããŠããŸããã Dottyã¯ããã©ã¡ãŒã¿ãŒåãããç¹æ§ã®äœ¿çšã«è¿œå ã®å¶éãå°å ¥ããŸããã
- ç¹æ§ã®ãã©ã¡ãŒã¿å€ã¯ãã¯ã©ã¹ãå®çŸ©ãããšãã«ã®ã¿æž¡ãããšãã§ããŸãããå¥ã®ç¹æ§ãæž¡ãããšã¯ã§ããŸãã
trait A(x: Int) trait B extends A trait B1 extends A(42) // class C extends A(42)
- ãã©ã¡ãŒã¿ãŒåãããç¹æ§ãå®è£
ããã¯ã©ã¹ãå®çŸ©ããå Žåããã©ã¡ãŒã¿ãŒå€ãæå®ããå¿
èŠããããŸãã ã¯ã©ã¹ãå¥ã®ã¯ã©ã¹ãæ¡åŒµããç¹å®ã®å€ãç¹æ§ã«æž¡ããããã©ãããå€æããå Žåããã®å Žåãå€ãæå®ããå¿
èŠã¯ãããŸããã
class D extends A // class D1 extends C class D2 extends C with A(84) // , C
- ãã©ã¡ãŒã¿åãããç¹æ§ã®åå«ã§ããã¯ã©ã¹ãæ¡åŒµããç¹æ§ã¯ããã®ç¹æ§ã®æ瀺çãªæ瀺ãéããŠå€ãæž¡ãå¿
èŠããããŸãã
class E extends B // , A class E extends A(42) with B
7.ãã³ããããã³ã°é 延å€
Scalaã®çŸåšã®ããŒãžã§ã³ã§ã¯ãlazy valã¯ãå«ãŸããŠãããªããžã§ã¯ãã®åæã¡ã«ããºã ã䜿çšããŠå®è£ ãããŠããŸãã ãã®ãœãªã¥ãŒã·ã§ã³ã«ã¯ã次ã®æ¬ ç¹ããããŸãã
- å€ã1ã€ã®ã¹ã¬ããã®ã¿ã§äœ¿çšãããå Žåãæå³ã®ãªãè¿œå ã®åæã³ã¹ãã
- æœåšçãªãããããã¯ãããšãã°ïŒ
object A { lazy val a1 = B.b1 lazy val a2 = 42 } object B { lazy val b1 = A.a2 }
2ã€ã®ã¹ã¬ãããåæã«å€a1ãšb1ã®åæåãéå§ãããšããããããªããžã§ã¯ãAãšBã®ããã¯ãååŸããŸãã b1ã®åæåã«ã¯ãªããžã§ã¯ãAã§ãŸã åæåãããŠããªãa2ã®å€ãå¿ èŠã§ããããã2çªç®ã®ã¹ã¬ããã¯ãªããžã§ã¯ãBã®ããã¯ã解é€ããããŸã§åŸ æ©ãããªããžã§ã¯ãBã®ããã¯ãä¿æããŸãããªããžã§ã¯ãBã®2çªç®ã®ã¹ã¬ããã«ãããããã¯ãåå ã§ãããã®çµæããããããã¯ãŸãã¯ãããããã¯ãçºçããŸããã ïŒãã®äŸã¯ãDmitry Petrashkoã«ããã¬ããŒãããåãããŠããŸã ïŒ
Dottyã§ã¯ãé 延å€ã®å Žåãã¹ã¬ããã»ãŒããªåæåããã£ã³ã»ã«ãããŸããã è€æ°ã®ã¹ã¬ããã§äœ¿çšããããã«å€ã®å®å šãªçºè¡ãå¿ èŠãªå Žåããã®ãããªå€æ°ã«ã¯æ¬¡ã®ããã«æ³šéãä»ããå¿ èŠããããŸãã
@volatile
@volatile lazy val x = {... some initialization code âŠ}
8.åæ
Dottyã¯åæåããµããŒãããŸããã ããããå®çŸ©ããããã®æ§æã¯ãJavaãšã®é¡æšã«ãã£ãŠè¡ãããŸããã
enum Color { case Red, Green, Blue }
åæã®ãµããŒãã¯ããœãŒã¹ã³ãŒã解æã®ã¬ãã«ã§å®è£ ãããŸãã ãã®æ®µéã§ãenumã³ã³ã¹ãã©ã¯ãã¯æ¬¡ã®åœ¢åŒã«å€æãããŸãã
sealed class Color extends Enum object Color { private def $new(tag: Int, name: String) = { new Color { val enumTag = tag def toString = name // } } val Red = $new(0, "Red") val Green = $new(1, "Green") val Blue = $new(2, "Blue") }
Javaãšåæ§ã«ãDottyã®åæåããã©ã¡ãŒã¿ãŒããµããŒãããŠããŸãã
enum Color(code: Int) { case Red extends Color(0xFF0000) case Green extends Color(0x00FF00) case Blue extends Color(0x0000FF) }
ãããã£ãŠãåæåã«ã¯ãå°å°ãããã±ãŒã¹ã¯ã©ã¹éå±€ã®ãã¹ãŠã®ããããã£ããããŸãã ããã«ãåæåã䜿çšãããšãååãã€ã³ããã¯ã¹ããŸãã¯ãã¹ãŠã®æå¹ãªå€ã®ã³ã¬ã¯ã·ã§ã³ã«ãã£ãŠå€ãååŸã§ããŸãã
val green = Color.enumValue(1) val blue = Color.enumValueNamed("Blue") val allColors = Color.enumValues
9.æé»çïŒæé»çïŒãã©ã¡ãŒã¿ãŒã®æ©èœã¿ã€ã
çŸåšã®Scalaèšèªå®è£ ã§ã¯ãæé»çãªé¢æ°ãã©ã¡ãŒã¿ãŒã¯ãå®è¡ã³ã³ããã¹ããè¡šãæšæºçãªæ¹æ³ã§ãã
def calculate(a: Int, b: Int)(implicit context: Context): Int = { val x = context.getInt("some.configuration.parameter") a * x + b }
ãã®äŸã§ã¯ãã³ã³ããã¹ãã¯æé»çã«æž¡ããããã®å€ã¯ããããæé»çãªã¹ã³ãŒãããååŸãããŸãã
implicit val context: Context = createContext() val result = calculate(1,2)
ãããã£ãŠãcalculateé¢æ°ãåŒã³åºããã³ã«ããã©ã¡ãŒã¿ãŒaãšbã®ã¿ãæž¡ãå¿ èŠããããŸãã ãã®ãããªåŒã³åºãããšã«ãã³ã³ãã€ã©ã¯ã察å¿ããæé»ã®ã¹ã³ãŒãããååŸããã³ã³ããã¹ãå€ã眮ãæããŸãã çŸåšã®ã¢ãããŒãã®äž»ãªåé¡ã¯ãæé»çãªãã©ã¡ãŒã¿ãŒã®åãã»ãããåãå€æ°ã®é¢æ°ã®å Žåããããã®é¢æ°ããšã«æå®ããå¿ èŠãããããšã§ãã
Dottyã§ã¯ãæé»çãªãã©ã¡ãŒã¿ãŒãåãé¢æ°ã¯åãšããŠè¡šãããšãã§ããŸãã
type Contextual[T] = implicit Context => T
Functionåã®å®è£ ã§ããéåžžã®é¢æ°ãšã®é¡æšã«ãããæé»çãªA => Båã®ãã¹ãŠã®å®è£ ã¯ã次ã®ç¹æ§ã®ãµãã¿ã€ãã«ãªããŸãã
trait ImplicitFunction1[-T0, +R] extends Function1[T0, R] { def apply(implicit x0: T0): R }
Dottyã¯ãåŒæ°ã®æ°ã«å¿ããŠã22ãŸã§ã®ImplicitFunctionç¹æ§ã®ããŸããŸãªå®çŸ©ãæäŸããŸãã
ãããã£ãŠãContextualåã䜿çšãããšã次ã®ããã«èšç®é¢æ°ããªãŒããŒã©ã€ãã§ããŸãã
def context: Contextual[Context] = implicitly[Context]
def calculate(a: Int, b: Int): Contextual[Int] = { val x = context.getInt("some.configuration.parameter") a * x + b }
ããã§ãç°å¢ããå¿ èŠãªã³ã³ããã¹ããååŸããç¹å¥ãªé¢æ°defã³ã³ããã¹ããå®çŸ©ããŸãã ãããã£ãŠãcalculateé¢æ°ã®æ¬äœã¯ããŸãå€æŽãããŠããŸããããã ããã³ã³ããã¹ããæ¬åŒ§ã§å²ãŸããªããªããåé¢æ°ã§å®£èšããå¿ èŠããªããªããŸããã
Dottyã«å«ãŸããŠããªããã®
ã¬ãã¥ãŒã®æåŸã«ãèšèªããåé€ãããèŠçŽ ã«ã€ããŠèª¬æããŸãã ååãšããŠãæ°ãã䟿å©ãªãã¶ã€ã³ã®å°å ¥åŸã«ãããã®å¿ èŠæ§ã¯æ¶æ» ããŸããããŸãã¯ããããã®å®è£ ã¯ããåé¡ãå€ããªãã競åãåŒãèµ·ããå§ãããããåé€ã容æã§ããããšãå€æããŸããã
ãããŠDottyãScalaèšèªã®æ°ããããŒãžã§ã³ã®åºç€ãšãªããããŒãžã§ã³çªå·ã¯ãã§ã«3.xxã«ãªã£ãŠããå¯èœæ§ãé«ãããã2.x.xèšèªã®ä»¥åã®ããŒãžã§ã³ãšã®åŸæ¹äºææ§ã¯ä¿èšŒãããŸããã ãã ããDottyéçºããŒã ã¯ãããŒãžã§ã³2.x.xãã3.x.xãžã®ç§»è¡ã容æã«ããç¹å¥ãªããŒã«ãéçºããããšãçŽæããŠããŸãã
1.ãããžã§ã¯ã·ã§ã³ãå ¥å
åå°åœ±ã¯ãTïŒAãšãã圢åŒã®æ§é äœã§ããTã¯ä»»æã®åã§ãAã¯Tåã®åãã£ãŒã«ãã§ãã次ã«äŸã瀺ããŸãã
trait T { type A val a: A def fun1(x: A): Any def fun2(x: T#A): Any }
次ã®2ã€ã®å€æ°ãå®çŸ©ãããŠãããšããŸãã
val t1: T = new T { ⊠} val t2: T = new T { ⊠}
ãã®å Žåãt1ã®fun1ã¡ãœãããžã®åŒæ°ã¯ãt2.aã§ã¯ãªããt1.aã®å€ã®ã¿ã§ãã ã¡ãœããã®åŒæ°ã¯ãã¿ã€ãTã®ã¿ã€ãAã®ãã£ãŒã«ãã®ä»»æã®å€ããšããŠå®çŸ©ãããŠãããããfun2ã¡ãœããã®åŒæ°ã¯t1.aãŸãã¯t2.aã®ããããã«ãªããŸãã
ãã®ãã¶ã€ã³ã¯ãå®å®ããŠããããã¿ã€ãã暪æãããšãã«è¡çªãåŒãèµ·ããå¯èœæ§ããããããé€å€ãããŸããã ããšãã°ã次ã®ã³ãŒãã¯ã³ã³ãã€ã«ãããŸãããå®è¡æã«ClassCastExceptionãã¹ããŒãããŸãïŒ ããããååŸïŒã
object Test { trait C { type A } type T = C { type A >: Any } type U = C { type A <: Nothing } type X = T & U def main(args: Array[String]) = { val y: X#A = 1 val z: String = y } }
åå°åœ±ã®ä»£ããã«ãäŸååïŒãã¹äŸååïŒãŸãã¯æé»çãªãã©ã¡ãŒã¿ãŒã䜿çšããããšããå§ãããŸãã
2.ååšã¿ã€ã
ååšåã¯ãä»ã®åã®ãã©ã¡ãŒã¿ãŒã§ããæªç¥ã®åãããããšã瀺ããŠããŸãããã®ã¿ã€ãã®å€ã¯ç§ãã¡ã«ã¯èå³ããããŸãã;ãããååšãããšããäºå®ã¯ç§ãã¡ã«ãšã£ãŠåã«éèŠã§ãããããã£ãŠãååããã®ã¿ã€ãã®ã¿ã€ãã¯ãäž»ã«Javaã®ãã©ã¡ãŒã¿ãŒåãããã¯ã€ã«ãã«ãŒããã¹ã¯ã¿ã€ããšã®äºææ§ã確ä¿ããããã«Scalaã«è¿œå ãããŸãããããšãã°ãJavaã®ã³ã¬ã¯ã·ã§ã³ã¯ãã©ã¡ãŒã¿ãŒåãããŠããããã©ã¡ãŒã¿ãŒã®çš®é¡ã«é¢å¿ããªãå Žåã¯ã次ã®ããã«ãã¹ã¯ã䜿çšããŠèšå®ã§ããŸãã
Iterable<?>
ãã©ã¡ãŒã¿ã®ã¿ã€ãã«èå³ããªãããå¶éã課ãããŠããããšãããã£ãŠããå Žåããã®å Žåãã¿ã€ãã¯æ¬¡ã®ããã«æ±ºå®ãããŸãã
Iterable<? extends Comparable>
Scalaã§ã¯ããããã®ã¿ã€ãã¯æ¬¡ã®ããã«å®çŸ©ãããŸãã
Iterable[T] forSome { type T } // Iterable[T] forSome { type T <: Comparable } //
Scalaã«ã¯ããã¹ã¯ã¿ã€ãããã©ã¡ãŒã¿ãŒåããæ©èœããããŸãã
Iterable[_] // Iterable[_ <: Comparable] //
æè¿ã®ããŒãžã§ã³ã§ã¯ããããã®èšé²åœ¢åŒã¯å®å šã«åçã§ãããããã£ãŠãX [T] forSome {type T}圢åŒãæŸæ£ããããšã決å®ãããŸãããäžè¬ã«ãforSomeèšèšã¯ããé¢åã§ããããåºã䜿çšãããŠããŸãããJavaã®åãšã®çµ±åãå¿ èŠãªã»ãŒãã¹ãŠã®å Žæã§ããã¹ã¯ã«ãããã©ã¡ãŒã¿ãŒåã䜿çšããæ§æã䜿çšãããããã«ãªããDottyã«æ®ãããšã決å®ãããŸããã
3.äºååæå
Scalaã®ç¹æ§ã«ã¯ãã©ã¡ãŒã¿ãŒããããŸãããããã¯ãããã€ãã®ç¹å®ã®ãã©ã¡ãŒã¿ãŒãäŸåããæœè±¡ãã©ã¡ãŒã¿ãŒã®äžéšãç¹æ§ã«ããå Žåã«åé¡ãåŒãèµ·ãããŸããã次ã®äŸãèããŠã¿ãŸãããã
trait A { val x: Int val b = x * 2 } class C extends A { val x = 10 } val c = new C
ãã®å Žåãcbã®å€ã¯20ã§ã¯ãªã0ã§ããåæåã®èŠåã«åŸã£ãŠãç¹æ§ã®æ¬äœãæåã«Scalaã§åæåããããã®åŸã§ã¯ã©ã¹ãåæåãããããã§ãããã£ãŒã«ãbãåæåãããæç¹ã§ã¯ãxã®å€ã¯ãŸã å®çŸ©ãããŠããªããããIntåã®ããã©ã«ãå€ãšããŠ0ã䜿çšãããŸãã
ãã®åé¡ã解決ããããã«ãScalaã¯äºååæåæ§æãå°å ¥ããŸãããããã䜿çšããŠãåã®äŸã®ãã°ãä¿®æ£ã§ããŸãã
class C extends {val x = 10} with A
ãã®èšèšã®æ¬ ç¹ã¯ãåçŽã«ããªã¢ãŒãã£ãºã ã䜿çšããã®ã§ã¯ãªããéèªæãªãœãªã¥ãŒã·ã§ã³ã«é Œãå¿ èŠãããããšã§ããç¹æ§ã®ãã©ã¡ãŒã¿ãŒã®å°å ¥ã«ãããåæã€ãã·ã£ã©ã€ã¶ãŒã®å¿ èŠæ§ã¯ãªããªããŸããããã®äŸã¯ãããã·ã³ãã«ã§ç解ããããæ¹æ³ã§å®è£ ã§ããŸãã
trait A(x: Int) { val b = x * 2 } class C extends A(10)
4.é 延åæå
Scalaã«ã¯é 延åæåã®ããã®ç¹å¥ãªç¹æ§ããããŸã
trait DelayedInit { def delayedInit(body: => Unit): Unit }
åæåäžã«ãã®ç¹æ§ãå®è£ ããã¯ã©ã¹ã¯ãdelayedInitã¡ãœãããåŒã³åºããŸãããã®ã¡ãœãããããbodyãã©ã¡ãŒã¿ãŒãä»ããŠã¯ã©ã¹ã®åæååãåŒã³åºãããšãã§ããŸãã
class Test extends DelayedInit { def delayedInit(body: => Unit): Unit = { println("This is delayedInit body") body } println("This is class body") }
ãããã£ãŠãæ°ããTestãªããžã§ã¯ããäœæãããšã次ã®åºåãåŸãããŸãã
ããã¯delayInitæ¬äœã§ã
ããã¯
Scalaã®ã¯ã©ã¹æ¬äœTrait DelayedInitã¯DeprecatedãšããŠå®£èšãããŠããŸããDottyã§ã¯ãç¹æ§ããã©ã¡ãŒã¿åã§ããããã«ãªã£ãããã圌ã¯ã©ã€ãã©ãªããå®å šã«é€å€ãããŸããããããã£ãŠãååã«ããåŒã³åºãã®ã»ãã³ãã£ã¯ã¹ã䜿çšãããšãåæ§ã®åäœãå®çŸã§ããŸãã
trait Delayed(body: => Unit) { println("This is delayed body") body } class Test extends Delayed(println("This is class"))
æ°ãããã¹ãåºåãäœæããå Žåãåæ§ã«ã次ã®ãšããã§ãã
ãã®å€ãäœãé ããŠãã
ãããã¯ãã¯ã©ã¹ã§ãããŸã
5.æç¶ãæ§æ
é¢æ°ã®å®£èšãçµ±äžããããã«ãè¿ãããåãUnitã§ããé¢æ°ãå®çŸ©ããããã®æç¶ãæ§æãæŸæ£ããããšã決å®ãããŸããã代ããã«
def run(args: List[String]) { //Method body }
ä»ãããªãã¯æžãå¿ èŠããããŸã
def run(args: List[String]): Unit = { //Method body }
ç¹ã«IntelliJ IDEAã®å€ãã®IDEããæç¶ãåã®æ§æãæ©èœçãªæ§æã«èªåçã«çœ®ãæããŠããããšã«æ³šæããŠãã ãããDottyã§ã¯ãã³ã³ãã€ã©ã¬ãã«ã§æ¢ã«æŸæ£ãããŠããŸããã
ãããã«
äžè¬ã«ãDottyã¯ãScalaã§ã®éçºäžã«çºçããé·æ延æ»ã®åé¡ã«å¯ŸããŠãããªãã·ã³ãã«ã§èå³æ·±ããœãªã¥ãŒã·ã§ã³ãæäŸããŸããããšãã°ãç§ã®å®è·µã§ã¯ãç¶æ¿éå±€ãä»ããŠæ¥ç¶ãããŠããªãè€æ°ã®ã¿ã€ãã®ãªããžã§ã¯ããåãå ¥ããããšã«ãªã£ãŠããã¡ãœãããèšè¿°ããå¿ èŠæ§ã«ã©ããããããåºäŒããŸãããåŒæ°ã®åãšããŠAnyã䜿çšãããã®åŸã«ãã¿ãŒã³ãããã³ã°ãè¡ãå¿ èŠããããŸããã Dottyã§ã¯ãåã®é£çµã«ãã£ãŠãã®åé¡ã解決ã§ããŸããããã«ãç§ã¯ç¹æ§ã®ãã©ã¡ãŒã¿ãŒãæ¬ ããŠããŸããå Žåã«ãã£ãŠã¯ããããã¯éåžžã«åœ¹ç«ã¡ãŸãã
äŒè°ã§ã®ã¬ããŒãããå€æãããšãScalaã³ãã¥ããã£ãŒã¯Dottyã®ãªãªãŒã¹ãåŸ ã£ãŠããŸããç¹ã«ãakkaãã¬ãŒã ã¯ãŒã¯ã«é¢ãã1ã€ã®ã¬ããŒãã§ãåä¿¡ã¡ãœãããšããŠãã¹ãŠã®ã¡ãã»ãŒãžãçµåããtypeã¡ãœãããæå®ããããšã«ãããã¢ã¯ã¿ãŒãã¿ã€ãããããšãã§ããæ¹æ³ã«ã€ããŠèª¬æããŸããã
Dottyã¯ãã§ã«è©Šçšã§ããŸããDottyWebãµã€ãã«ã¯ãã€ã³ã¹ããŒã«ãšæ§æã®æé ãèšèŒãããŠããŸãããã ãããŸã äžå®å®ã§ãããããèè ã¯ãŸã ç£æ¥ã³ãŒãã§ã®äœ¿çšãæšå¥šããŠããŸããã
èè ã«ã€ããŠ
ç§ã®ååã¯ã¢ã¬ã¯ãµã³ããŒãã«ã¬ãã§ããããµãŒããŒãœãããŠã§ã¢ã10幎以äžéçºããŠããŸãã圌ã¯PHPéçºè ãšããŠå§ãŸããJavaã«åãæ¿ããæè¿Scalaã«åãæ¿ããŸããã 2015幎以æ¥ãç§ã¯CleverDATAã§åããŠããŸãããã§ãScalaã¯JavaãšPythonãšãšãã«äž»èŠãªéçºèšèªã®1ã€ã§ããç§ãã¡ã¯äž»ã«ãApache Sparkã䜿çšããŠå€§éã®ããŒã¿ãåŠçããããã»ã¹ãéçºããAkka Streamsã«åºã¥ããŠå€éšã·ã¹ãã ãšããåãããããã®é«è² è·ã®RESTãµãŒãã¹ãæ§ç¯ããããã«Scalaã䜿çšããŸãã
è¿œå è³æ
- 2017幎5æã®Scala Daysã³ãã³ããŒã²ã³äŒè°ã§ã®Martin Oderskyã®ã¬ããŒãïŒãããª
- å
¬åŒScalaèšèªãµã€ã
- Dottyãããžã§ã¯ãã®å
¬åŒãµã€ã
- èšäº Scalaã®èšèªã«ã€ããŠã®ãŠã£ãããã£ã¢ã§
- ãããèšç®
- èšäºScalaã®æ¬è³ª
- Martin Oderskyã«ãã DOT on YOWã«ã€ããŠã®ã¬ããŒãïŒå€ã2017幎2æ
- Dottyã®éçºè
ã®1人ã§ããDmitry Petrashkoã«ããã¬ããŒã
- çš®é¡ã®å€ã
- æé»çãªé¢æ°ã¿ã€ã