Coding in Style
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

Coding in Style

  • 1,206 views
Uploaded on

Scala Conference in Japan 2013

Scala Conference in Japan 2013

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,206
On Slideshare
1,198
From Embeds
8
Number of Embeds
3

Actions

Shares
Downloads
24
Comments
0
Likes
3

Embeds 8

http://librosweb.es 5
https://twitter.com 2
http://lw.192.168.2.13.xip.io 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Coding in Style J. Suereth Senior Software Engineer粋なコード
  • 2. Agenda ● The Scala mindset ● Scala 2.10 new features ● A brave new ventureScala 風に考える/Scala 2.10 の新機能/その先へ
  • 3. Favor Expressions文より式
  • 4. def isAwesome(data: Data): Boolean = { if(data.awesome) return true if(data.lame) return false return data.contains("Tasty Sandwich")}
  • 5. def isAwesome(data: Data): Boolean = if(data.awesome) true else if(data.lame) false else (data contains "Tasty Sandwich")}
  • 6. def isAwesome(data: Data): Boolean = (data.awesome || (!data.lame) || (data contains "Tasty Sandwich"))
  • 7. Embrace Operator Notation演算子(中置)記法を取り入れよう
  • 8. def privs(user: Option[User]): Privileges = user.map(findUserPrivileges).getOrElse( NoPrivs)
  • 9. def privs(user: Option[User]): Privileges = (user map findUserPrivileges getOrElse NoPrivs)
  • 10. Let the language do the work SUDO Make me a variable作業を言語に任せる
  • 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. 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. Tail-recursioN! @tailrec def read(): Unit = (in read buf) match { case 0 => () case n => out.write(buf, 0, n) read() }
  • 14. Tail-recursioN! @tailrec def read(): Unit = (in read buf) match { Base Case case 0 => () case n => out.write(buf, 0, n) read() }
  • 15. Tail-recursioN! @tailrec def read(): Unit = (in read buf) match { case 0 => () Recursive Case case n => out.write(buf, 0, n) read() }
  • 16. If it seems useful, look for it便利そうであれば、まずは探そう
  • 17. def countEm(counts: Seq[Int]): Int = { var total = 0 for(count <- counts) total += count total}
  • 18. def countEm(counts: Seq[Int]): Int = counts.sum
  • 19. Collections! ● Scala collections have > 100 useful methods ● By far the biggest reason to use Scala is manipulating data using collectionsScala を使う最大の理由: コレクションを使ったデータ処理
  • 20. Aim Higher higher-order-functions, that is上を狙おう (高階関数)
  • 21. def sort[T]( data: Seq[T])( lessThan: (T,T) => Boolean): Seq[T] = ...
  • 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. New w/ Scala 2.10 Features that alter your daily codeScala 2.10 の新機能
  • 24. Build strings the nice way interpolators文字列生成を楽に
  • 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. Keep the abstract.... .... well abstract.抽象的なものは抽象的に
  • 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. 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. Add behavior with shiny new value classes and implicit classes値クラスとimplicit クラスで振る舞いを追加する
  • 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. 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. 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. Cheat in an Emergency With Dynamic Typesいざという時の動的型
  • 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. 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. Promise the Future! Make sure to deliverPromise とFuture (約束は守りましょう)
  • 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. 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. 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. 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. Scalas Futures Provide a lightweight model for asynchronous, non-blocking execution that can be chained and joined throughout your application.Future: 軽量な非同期・ノンブロッキング実行モデル
  • 42. Staying Async! See http://jsuereth.com/intro-to-fp/いつも非同期で
  • 43. trait AsynchService { def users: Future[Seq[User]] def projects(user: User):Future[Seq[Project]]}
  • 44. def allprojects(api: AsynchService): Future[Set[Project]] = (Future.traverse(api.users)(api.projects) map (_.flatten.toSet))
  • 45. Traverse is fork join def traverse[A]( seq: Future[Seq[A]] )( op: A => Future[B] ): Future[Seq[B]] = ....traverse は fork/join を用いて行われる
  • 46. Feeling Crazy? Manipulate some ASTsちょっと遊ぶ?AST をいじろう
  • 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. 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. 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. Tree Transformation object Bar { assert(false, "THIS IS A BAD OBJECT") }構文木の変換
  • 51. object Bar { Expr[Boolean]} Expr[Any]
  • 52. object Bar { Macro Expr[Boolean]} Expr[Any]
  • 53. object Bar { Expr[Unit] Macro}
  • 54. object Bar { ()}
  • 55. A Brave New World Welcome toすばらしい新世界へようこそ
  • 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. 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. Questions?質問ある?