Scalaのオブジェクトの話

51
2014.6.25 第8回 Functional 忍者 前康 (@maeda) Scalaの オブジェクト の話

description

Scalaの関数型プログラミングの中で、オブジェクトがどのような位置づけで使用されるかの説明した資料です。object, class, traitがMLのモジュールシステムとどのように対応するかを中心に解説しています。

Transcript of Scalaのオブジェクトの話

  • 1. 2014.6.25 Functional (@maeda_) Scala

2. ( twitter : @maeda_ ) ( http://www.illi-ichi.com ) 3. Scala Scala 4. Scala = 5. Scala 6. Scala 1. Java 2. ML Scala case class case object object class HaskellML ML Modules and Haskell Type Classes: A Constructive Comparison http://www.cse.unsw.edu.au/~chak/papers/modules-classes.pdf 7. Scala 1. Java 2. ML Scala case class case object object class HaskellML ML Modules and Haskell Type Classes: A Constructive Comparison http://www.cse.unsw.edu.au/~chak/papers/modules-classes.pdf 8. / 9. object (= ) objectHoge{ deffoo(...)=... } Hoge.foo(...)//Hogefoo classHogeClass(){ deffoo(...)=... } valHoge=newHogeClass() 10. classHoge(connectionString:String){ deffoo(...)=... } // valhoge=newHoge("jdbc:h2:mem:test") hoge.foo(...) 11. packageimport classHoge(fuga:Fuga){ importfuga._ ... } Scalaimport 12. Javastatic //private classHogeprivate(...){...} objectHoge{ //Hoge deffromString(str:String):Hoge=newHoge(...) deffromFile(file:File):Hoge=newHoge(...) } REPL:paste 13. 14. valmenu:Map[String,Action]=Map( "hungry"->GoTo("restaurant"), "tired"->Sleep, ... ) Parser.parse("")//NoInput Parser.parse("hun")//Entering(GoTo("restaurant"),3) Parser.parse("hunt")//WrongInput Parser.parse("hungry")//Completed(GoTo("restaurant")) 15. objectParser{ sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:Action,count:Int)extendsState caseclassCompleted(action:Action)extendsState caseobjectWrongInputextendsState valmenu:Map[String,Action]= Map("hungry"->GoTo("restaurant"),"tired"->Sleep,...) defparse(Stringinput):State=... defmaxMenuLength:Int=... } Parser.parse("hun")//Parser.Entering(Parser.GoTo("restaurant"),3) Parser.parse("hunt")//Parser.WrongInput #1 object 16. objectParser{ sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:Action,count:Int)extendsState caseclassCompleted(action:Action)extendsState caseobjectWrongInputextendsState valmenu:Map[String,Action]= Map("hungry"->GoTo("restaurant"),"tired"->Sleep,...) defparse(Stringinput):State=... defmaxMenuLength:Int=... } Parser.parse("hun")//Parser.Entering(Parser.GoTo("restaurant"),3) Parser.parse("hunt")//Parser.WrongInput Parser Parser #1 object 17. objectParser{ sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:Action,count:Int)extendsState caseclassCompleted(action:Action)extendsState caseobjectWrongInputextendsState valmenu:Map[String,Action]= Map("hungry"->GoTo("restaurant"),"tired"->Sleep,...) defparse(Stringinput):State=... defmaxMenuLength:Int=... } Parser.parse("hun")//Parser.Entering(Parser.GoTo("restaurant"),3) Parser.parse("hunt")//Parser.WrongInput #1 object 18. objectParser{ sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:Action,count:Int)extendsState caseclassCompleted(action:Action)extendsState caseobjectWrongInputextendsState valmenu:Map[String,Action]= Map("hungry"->GoTo("restaurant"),"tired"->Sleep,...) defparse(Stringinput):State=... defmaxMenuLength:Int=... } Parser.parse("hun")//Parser.Entering(Parser.GoTo("restaurant"),3) Parser.parse("hunt")//Parser.WrongInput #1 object 19. objectParser{ sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:Action,count:Int)extendsState caseclassCompleted(action:Action)extendsState caseobjectWrongInputextendsState valmenu:Map[String,Action]= Map("hungry"->GoTo("restaurant"),"tired"->Sleep,...) defparse(Stringinput):State=... defmaxMenuLength:Int=... } Parser.parse("hun")//Parser.Entering(Parser.GoTo("restaurant"),3) Parser.parse("hunt")//Parser.WrongInput #1 object 20. sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction classParser(menu:Map[String,Action]){ sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:Action,count:Int)extendsState caseclassCompleted(action:Action)extendsState caseobjectWrongInputextendsState defparse(Stringinput):State=... defmaxMenuLength:Int=... } valparser=newParser( Map("hungry"->GoTo("restaurant"),"tired"->Sleep,...)) parser.parse("hun")//parser.Entering(GoTo("restaurant"),3) parser.parse("hunt")//parser.WrongInput #2 21. sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction classParser(menu:Map[String,Action]){ sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:Action,count:Int)extendsState caseclassCompleted(action:Action)extendsState caseobjectWrongInputextendsState defparse(Stringinput):State=... defmaxMenuLength:Int=... } valparser=newParser( Map("hungry"->GoTo("restaurant"),"tired"->Sleep,...)) parser.parse("hun")//parser.Entering(GoTo("restaurant"),3) parser.parse("hunt")//parser.WrongInput #2 class 22. sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction classParser(menu:Map[String,Action]){ sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:Action,count:Int)extendsState caseclassCompleted(action:Action)extendsState caseobjectWrongInputextendsState defparse(Stringinput):State=... defmaxMenuLength:Int=... } valparser=newParser( Map("hungry"->GoTo("restaurant"),"tired"->Sleep,...)) parser.parse("hun")//parser.Entering(GoTo("restaurant"),3) parser.parse("hunt")//parser.WrongInput #2 Action Parser 23. sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction classParser[A](menu:Map[String,A]){ sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:A,count:Int)extendsState caseclassCompleted(action:A)extendsState caseobjectWrongInputextendsState defparse(Stringinput):State=... defmaxMenuLength:Int=... } valparser:Parser[Action]=newParser( Map("hungry"->GoTo("restaurant"),"tired"->Sleep,...)) parser.parse("hun")//parser.Entering(GoTo("restaurant"),3) parser.parse("hunt")//parser.WrongInput #3 24. sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction classParser[A](menu:Map[String,A]){ sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:A,count:Int)extendsState caseclassCompleted(action:A)extendsState caseobjectWrongInputextendsState defparse(Stringinput):State=... defmaxMenuLength:Int=... } valparser:Parser[Action]=newParser( Map("hungry"->GoTo("restaurant"),"tired"->Sleep,...)) parser.parse("hun")//parser.Entering(GoTo("restaurant"),3) parser.parse("hunt")//parser.WrongInput #3 Parser 25. abstractclassParser{ typeA defmenu:Map[String,A] sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:A,count:Int)extendsState caseclassCompleted(action:A)extendsState caseobjectWrongInputextendsState defparse(Stringinput):State=... defmaxMenuLength:Int=... } sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction valparser:Parser=newParser{ typeA=Action valmenu=Map("hungry"->GoTo("restaurant"), "tired"->Sleep,...) } parser.parse("hun")//parser.Entering(GoTo(Restaurant),3) parser.parse("hunt")//parser.WrongInput #4 26. abstractclassParser{ typeA defmenu:Map[String,A] sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:A,count:Int)extendsState caseclassCompleted(action:A)extendsState caseobjectWrongInputextendsState defparse(Stringinput):State=... defmaxMenuLength:Int=... } sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction valparser:Parser=newParser{ typeA=Action valmenu=Map("hungry"->GoTo("restaurant"), "tired"->Sleep,...) } parser.parse("hun")//parser.Entering(GoTo(Restaurant),3) parser.parse("hunt")//parser.WrongInput #4 27. abstractclassParser{ typeA defmenu:Map[String,A] sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:A,count:Int)extendsState caseclassCompleted(action:A)extendsState caseobjectWrongInputextendsState defparse(Stringinput):State=... defmaxMenuLength:Int=... } sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction valparser:Parser=newParser{ typeA=Action valmenu=Map("hungry"->GoTo("restaurant"), "tired"->Sleep,...) } parser.parse("hun")//parser.Entering(GoTo(Restaurant),3) parser.parse("hunt")//parser.WrongInput #4 28. abstractclassParser{ typeAction defmenu:Map[String,Action] sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:Action,count:Int)extendsState caseclassCompleted(action:Action)extendsState caseobjectWrongInputextendsState defparse(Stringinput):State=... defmaxMenuLength:Int=... } valparser:Parser=newParser{ sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction valmenu=Map("hungry"->GoTo("restaurant"), "tired"->Sleep,...) } parser.parse("hun")//parser.Entering(GoTo(Restaurant),3) parser.parse("hunt")//parser.WrongInput #5Action 29. abstractclassParser{ typeAction defmenu:Map[String,Action] sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:Action,count:Int)extendsState caseclassCompleted(action:Action)extendsState caseobjectWrongInputextendsState defparse(Stringinput):State=... defmaxMenuLength:Int=... } valparser:Parser=newParser{ sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction valmenu=Map("hungry"->GoTo("restaurant"), "tired"->Sleep,...) } parser.parse("hun")//parser.Entering(GoTo(Restaurant),3) parser.parse("hunt")//parser.WrongInput #5Action 30. abstractclassParser{ typeAction defmenu:Map[String,Action] sealedabstractclassState caseobjectNoInputextendsState caseclassEntering(action:Action,count:Int)extendsState caseclassCompleted(action:Action)extendsState caseobjectWrongInputextendsState defparse(Stringinput):State=... defmaxMenuLength:Int=... } objectSomeParserextendsParser{ sealedabstractclassAction caseclassGoTo(place:String)extendsAction caseobjectSleepextendsAction valmenu=Map("hungry"->GoTo("restaurant"),"tired"->Sleep,...) } SomeParser.parse("hun")//SomeParser.Entering(GoTo("restaurant"),3) SomeParser.parse("hunt")//SomeParser.WrongInput #6 object 31. JavaInner Class valsomeParser=newParser(...) valantotherParser=newParser(...) someParser.parse(...)//someParser.During(...) anotherParser.parse(...)//anotherParser.During(...) // valstate:someParser.State=anotherParser.parse(...) 32. Scala () ScalaML... in OCaml 33. Scala A () A () abstractclassKlass{ typeA defshow:A=>String } abstractclassKlass[A]{ defshow:A=>String } Scala(forSome) forSome 34. 35. ... // classParser[A](menu:Map[String,A]){ defparse(input:String):State[A]=... } // defparse[A](menu:Map[String,A])(input:String):State[A]=... valparser:String=>State[Action]=parse(Map(...)) 36. 2 ML // classParser[A](menu:Map[String,A]){ defparse(input:String):State[A]=... defmaxMenuLength:Int=... } // typeParser[A]={ defparse(input:String):State[A] defmaxMenuLength:Int } defcreateParser[A](menu:Map[String,A]):Parser=... 37. ML OCaml Scala Java 38. ... ( ) (RCATWD) http://www.infoq.com/jp/news/2010/07/objects-smalltalk-erlang 39. trait 40. trait trait objectHoge{ } traitSomePart{ } traitAnotherPart{ } //trait(mix-in) objectHogeextendsSomePart withAnotherPart Some Functions Another Functions Some Functions Another Functions 41. mix-in //object objectHogeextendsSomePartwithAnotherPart //mix-in valhoge=newSomePartwithAnotherPart valfuga=newSomePartwithYetAnotherPart //mix-in valfoo=if(config.availableXXX)newSomePartwithXXX elsenewSomePartwithDefault 42. (self type) traittrait objectHoge{ } traitSomePart{ } traitAnotherPart{this:SomePart=> } objectHogeextendsSomePart withAnotherPart Some Functions Another Functions Some Functions Another Functions Call mix-in SomePart 43. trait trait mix-in traitHogeSignature{// deffunc(arg:Int):String } traitFuga{this:HogeSignature=>// ... } traitHogeextendsHogeSignature{// deffunc(arg:Int):String=... } objectSomeModuleextendsFugawithHoge// 44. MLsignature ML structure(struct) signature(sig) traitMLsignature (*OCamlREPL*) # module Three = struct let x = 3 end;; module Three : sig val x : int end # module type X_int = sig val x : int end;; module type X_int = sig val x : int end # module Increment (M : X_int) = struct let x = M.x + 1 end;; module Increment : functor (M : X_int) -> sig val x : int end Real World OcamlChapter 9 Functor 45. trait DSL //ScalaTest //ShouldMatchermix-in... classHogeSpecextendsSpecificationwithShouldMatcher{ //should "hoge"in{ hogeshouldequal(3) } //Akka(Actor) //ActorLoggingmix-in... classHogeActorextendsActorwithActorLogging{ // defreceive={... 46. 47. Scala 48. pure State valhoge=newHoge(bufferSize=100)// valresult1=hoge.heavyCalc(10) valresult2=hoge.heavyCalc(10) valcache=Cache.empty(bufferSize=100) val(result1,cache1)=Hoge.heavyCalc(10,cache) val(result2,cache2)=Hoge.heavyCalc(10,cache1) 49. override overrideStackable Trait () http://www.artima.com/scalazine/articles/stackable_trait_pattern.html ""in{ valstub=newSomeStub{overridedefhoge(...)=...} ... } ""in{ valstub=newSomeStub{overridedeffuga(...)=...} ... } traitHogewithFuga{ abstractoverridedeffoo(x:X)=super.foo(modify(x)) ... 50. case object sealedabstractclassErrorReason(valerrorCode:String) caseobjectInvalidInputextendsErrorReason("E001") caseobjectNotAuthorizedextendsErrorReason("E002") ... 51. Scala Scala