Coding in Style

1,317 views
1,168 views

Published on

Scala Conference in Japan 2013

0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,317
On SlideShare
0
From Embeds
0
Number of Embeds
15
Actions
Shares
0
Downloads
26
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

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?質問ある?

×