Upcoming SlideShare
×

# Coding in Style

1,317 views
1,168 views

Published on

Scala Conference in Japan 2013

3 Likes
Statistics
Notes
• Full Name
Comment goes here.

Are you sure you want to Yes No
• Be the first to comment

Views
Total views
1,317
On SlideShare
0
From Embeds
0
Number of Embeds
15
Actions
Shares
0
26
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?質問ある？