Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Coding in Style

1,473 views

Published on

Scala Conference in Japan 2013

  • Be the first to comment

Coding in Style

  1. 1. Coding in Style J. Suereth Senior Software Engineer粋なコード
  2. 2. Agenda ● The Scala mindset ● Scala 2.10 new features ● A brave new ventureScala 風に考える/Scala 2.10 の新機能/その先へ
  3. 3. Favor Expressions文より式
  4. 4. def isAwesome(data: Data): Boolean = { if(data.awesome) return true if(data.lame) return false return data.contains("Tasty Sandwich")}
  5. 5. def isAwesome(data: Data): Boolean = if(data.awesome) true else if(data.lame) false else (data contains "Tasty Sandwich")}
  6. 6. def isAwesome(data: Data): Boolean = (data.awesome || (!data.lame) || (data contains "Tasty Sandwich"))
  7. 7. Embrace Operator Notation演算子(中置)記法を取り入れよう
  8. 8. def privs(user: Option[User]): Privileges = user.map(findUserPrivileges).getOrElse( NoPrivs)
  9. 9. def privs(user: Option[User]): Privileges = (user map findUserPrivileges getOrElse NoPrivs)
  10. 10. Let the language do the work SUDO Make me a variable作業を言語に任せる
  11. 11. def slurp(file : File): String = { var input: InputStream = null var output: OutputStream = null var read = 0 try { input = new FileInputStream(file) output = new StringOutputStream() val buf = new Array[Byte](BUF_SIZE) read = input.read(buf) while(read > 0) { output.write(buf, 0, read) read = input.read(buf) } } finally { if(input != null) input.close() if(output != null) output.close() } if(output != null) return output.toString return null}
  12. 12. def slurp(in: File): String = { val in = new FileInputStream(in) val out = new StringWriter() val buf = new Array[Byte](BUF_SIZE) def read(): Unit = (in read buf) match { case 0 => () case n => out.write(buf, 0, n) read() } try read() finally in.close() out.toString}
  13. 13. Tail-recursioN! @tailrec def read(): Unit = (in read buf) match { case 0 => () case n => out.write(buf, 0, n) read() }
  14. 14. Tail-recursioN! @tailrec def read(): Unit = (in read buf) match { Base Case case 0 => () case n => out.write(buf, 0, n) read() }
  15. 15. Tail-recursioN! @tailrec def read(): Unit = (in read buf) match { case 0 => () Recursive Case case n => out.write(buf, 0, n) read() }
  16. 16. If it seems useful, look for it便利そうであれば、まずは探そう
  17. 17. def countEm(counts: Seq[Int]): Int = { var total = 0 for(count <- counts) total += count total}
  18. 18. def countEm(counts: Seq[Int]): Int = counts.sum
  19. 19. Collections! ● Scala collections have > 100 useful methods ● By far the biggest reason to use Scala is manipulating data using collectionsScala を使う最大の理由: コレクションを使ったデータ処理
  20. 20. Aim Higher higher-order-functions, that is上を狙おう (高階関数)
  21. 21. def sort[T]( data: Seq[T])( lessThan: (T,T) => Boolean): Seq[T] = ...
  22. 22. Why higher order functions? def sort[T]( data: Seq[T] )( lessThan: (T,T) => Boolean ): Seq[T] = ... Abstract the algorithm (how to do something) from the goal (what to do)目的(何がしたいか) とアルゴリズム(どうやるか) を分離する
  23. 23. New w/ Scala 2.10 Features that alter your daily codeScala 2.10 の新機能
  24. 24. Build strings the nice way interpolators文字列生成を楽に
  25. 25. val HAI = "HI"val name = "SQUARE"val height = 100val width = 20scala> val x = s"${HAI}"x: String = HIscala> f"$name is $height%04d meters by$width%04d meters"res0: String = SQUARE is 0100 meters by 0020meters
  26. 26. Keep the abstract.... .... well abstract.抽象的なものは抽象的に
  27. 27. A Graph Library APItrait Node[N] { trait Graph[N,E] { def value: N type Nd = Node[N]} type Ed = Edge[N,E]trait Edge[N,E] { def value: E def nodes: Set[Nd] def from: Node[N] def edges(n: Nd): Seq[Ed] def to: Node[N] }}
  28. 28. A Graph Library API trait Node[N] { trait Graph[N,E] { def value: N type Nd = Node[N] } Great for implementers, type Ed = Edge[N,E] trait but wheres all the Edge[N,E] { def friendly user methods? Set[Nd] value: E def nodes: def from: Node[N] def edges(n: Nd): Seq[Ed] def to: Node[N] } }実装する人にはいいけど、trait を使う人にやさしくない
  29. 29. Add behavior with shiny new value classes and implicit classes値クラスとimplicit クラスで振る舞いを追加する
  30. 30. object Graph { implicit class Ops[N,E](val g: Graph[N,E]) extends AnyVal { def isAcyclic: Boolean = cycles forall (c => (c drop 1).isEmpty) def cycles: Set[Set[Node[N]]] = ... compute using tarjan or other algorithm ... }}
  31. 31. object Graph { implicit class Ops[N,E](val g: Graph[N,E]) extends AnyVal { def isAcyclic: Boolean = cycles forall (c => (c drop 1).isEmpty) def cycles: Set[Set[Node[N]]] = ... compute using tarjan or other algorithm ... }}
  32. 32. Fast at runtime, too val graph: Graph[N, E] = ... if(graph.isCyclic) sys.error("O NOES") Translates to static helper method call val graph: Graph[N, E] = ... if(Graph.Ops.isCyclic(graph)) sys.error("O NOES")実行時には static メソッドの呼び出しへと変換される
  33. 33. Cheat in an Emergency With Dynamic Typesいざという時の動的型
  34. 34. class MapHelper(json: Map[String,AnyRef]) extends Dynamic { def selectDynamic(name: String) = (json get name getOrElse sys.error(s"Attribute $namenot found in json: $json"))}
  35. 35. scala> val m = new MapHelper(Map[String,AnyRef]("name" -> "Jimmy", "age" -> "10"))m: MapHelper = MapHelper@683f67e0scala> m.nameres1: AnyRef = Jimmyscala> m.sexjava.lang.RuntimeException: Attribute sexnot found in json: Map(name -> Jimmy, age ->10)
  36. 36. Promise the Future! Make sure to deliverPromise とFuture (約束は守りましょう)
  37. 37. import scala.concurrent._import scala.concurrent.ExecutionContext.Implicits.globalscala> val x = promise[Int]scala> val y = x.futurescala> y.isCompletedres5: Boolean = falsescala> x success 5scala> y.isCompletedres7: Boolean = truescala> y.valueres9: Option[Either[Throwable,Int]] = Some(Right(5))
  38. 38. Why not Java Futures?future { executor.submit( Thread sleep 30000L 5 new} Callable<Integer>( ) { def call(): Creating! Integer = { Thread sleep 3000L new Integer(5) }
  39. 39. Why not Java Futures?val x: Future[Int] = val x: Future[Integer] ... = ...Await.result(x, 10 seconds) x.get(10, Blo TimeUnit.SECONDS) cki ng !
  40. 40. Why not Java Futures?val x: Future[Int] = N/A ...val y: Future[Int] = x map { result => result + 5 king } l oc -B ! on ins N a ch
  41. 41. Scalas Futures Provide a lightweight model for asynchronous, non-blocking execution that can be chained and joined throughout your application.Future: 軽量な非同期・ノンブロッキング実行モデル
  42. 42. Staying Async! See http://jsuereth.com/intro-to-fp/いつも非同期で
  43. 43. trait AsynchService { def users: Future[Seq[User]] def projects(user: User):Future[Seq[Project]]}
  44. 44. def allprojects(api: AsynchService): Future[Set[Project]] = (Future.traverse(api.users)(api.projects) map (_.flatten.toSet))
  45. 45. Traverse is fork join def traverse[A]( seq: Future[Seq[A]] )( op: A => Future[B] ): Future[Seq[B]] = ....traverse は fork/join を用いて行われる
  46. 46. Feeling Crazy? Manipulate some ASTsちょっと遊ぶ?AST をいじろう
  47. 47. object MacroAsserts { def assert(cond: Boolean, expr: String) = macro assertImpl def assertImpl(c: Context)( cond: c.Expr[Boolean], msg: c.Expr[String] ): c.Expr[Unit] = if(sys.env("SCALA_ASSERT") == "true") c.reify(if(cond.splice) sys.error(msg.splice)) else c.reify(())}
  48. 48. object MacroAsserts { What the user sees def assert(cond: Boolean, expr: String) = macro assertImpl def assertImpl(c: Context)( cond: c.Expr[Boolean], msg: c.Expr[String] ): c.Expr[Unit] = if(sys.env("SCALA_ASSERT") == "true") c.reify(if(cond.splice) sys.error(msg.splice)) else c.reify(())}
  49. 49. object MacroAsserts { def assert(cond: Boolean, expr: String) = macro assertImpl def assertImpl(c: Context)( cond: c.Expr[Boolean], msg: c.Expr[String] ): c.Expr[Unit] = if(sys.env("SCALA_ASSERT") == "true") c.reify(if(cond.splice) sys.error(msg.splice)) else c.reify(())} What the compiler uses
  50. 50. Tree Transformation object Bar { assert(false, "THIS IS A BAD OBJECT") }構文木の変換
  51. 51. object Bar { Expr[Boolean]} Expr[Any]
  52. 52. object Bar { Macro Expr[Boolean]} Expr[Any]
  53. 53. object Bar { Expr[Unit] Macro}
  54. 54. object Bar { ()}
  55. 55. A Brave New World Welcome toすばらしい新世界へようこそ
  56. 56. Whats coming in Scala 2.11? Nothing certain, but a list of possibilities ● Smaller ○ Modularization of components? ○ Eviction of deprecated libraries? ● Faster ○ More reliable inlining? ○ Method-Handle based closures? ● Stabler ○ Fix ALL THE BUGS ○ Reflection API Stabilizes?より小さく、高速で、安定した Scala 2.11
  57. 57. ResourcesCollections: http://docs.scala-lang.org/overviews/collections/introduction.htmlString Interpolation: http://docs.scala-lang.org/overviews/core/string-interpolation.htmlValue Classes: http://docs.scala-lang.org/overviews/core/value-classes.htmlFutures: http://docs.scala-lang.org/overviews/core/futures.htmlReflection: http://docs.scala-lang.org/overviews/reflection/overview.htmlMacros: http://docs.scala-lang.org/overviews/macros/overview.html
  58. 58. Questions?質問ある?

×