Upload
scalaconfjp
View
930
Download
7
Embed Size (px)
DESCRIPTION
Scala Conference in Japan 2013
Citation preview
Coding in StyleJ. Suereth
Senior Software Engineer
粋なコード
Agenda● The Scala mindset● Scala 2.10 new features● A brave new venture
Scala 風に考える/Scala 2.10 の新機能/その先へ
Favor Expressions
文より式
def isAwesome(data: Data): Boolean = { if(data.awesome) return true if(data.lame) return false return data.contains("Tasty Sandwich")}
def isAwesome(data: Data): Boolean = if(data.awesome) true else if(data.lame) false else (data contains "Tasty Sandwich")}
def isAwesome(data: Data): Boolean = (data.awesome || (!data.lame) || (data contains "Tasty Sandwich"))
Embrace Operator Notation
演算子(中置)記法を取り入れよう
def privs(user: Option[User]): Privileges = user.map(findUserPrivileges).getOrElse( NoPrivs)
def privs(user: Option[User]): Privileges = (user map findUserPrivileges getOrElse NoPrivs)
Let the language do the work
SUDO Make me a variable
作業を言語に任せる
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}
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}
Tail-recursioN! @tailrec def read(): Unit = (in read buf) match { case 0 => () case n => out.write(buf, 0, n) read() }
Tail-recursioN! @tailrec def read(): Unit = (in read buf) match { case 0 => () case n => out.write(buf, 0, n) read() }
Base Case
Tail-recursioN! @tailrec def read(): Unit = (in read buf) match { case 0 => () case n => out.write(buf, 0, n) read() }
Recursive Case
If it seems useful, look for it
便利そうであれば、まずは探そう
def countEm(counts: Seq[Int]): Int = { var total = 0 for(count <- counts) total += count total}
def countEm(counts: Seq[Int]): Int = counts.sum
Collections!● Scala collections have > 100 useful methods● By far the biggest reason to use Scala is
manipulating data using collections
Scala を使う最大の理由: コレクションを使ったデータ処理
Aim Higherhigher-order-functions, that is
上を狙おう (高階関数)
def sort[T]( data: Seq[T])( lessThan: (T,T) => Boolean): Seq[T] = ...
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)
目的(何がしたいか) とアルゴリズム(どうやるか) を分離する
New w/ Scala 2.10Features that alter your daily code
Scala 2.10 の新機能
Build strings the nice wayinterpolators
文字列生成を楽に
val HAI = "HI"val name = "SQUARE"val height = 100val width = 20
scala> val x = s"${HAI}"x: String = HI
scala> f"$name is $height%04d meters by $width%04d meters"res0: String = SQUARE is 0100 meters by 0020 meters
Keep the abstract........ well abstract.
抽象的なものは抽象的に
A Graph Library APItrait Node[N] { def value: N}trait Edge[N,E] { def value: E def from: Node[N] def to: Node[N]}
trait Graph[N,E] { type Nd = Node[N] type Ed = Edge[N,E] def nodes: Set[Nd] def edges(n: Nd): Seq[Ed]}
A Graph Library APItrait Node[N] { def value: N}trait Edge[N,E] { def value: E def from: Node[N] def to: Node[N]}
trait Graph[N,E] { type Nd = Node[N] type Ed = Edge[N,E] def nodes: Set[Nd] def edges(n: Nd): Seq[Ed]}
Great for implementers, but where's all the friendly user methods?
実装する人にはいいけど、trait を使う人にやさしくない
Add behaviorwith shiny new value classes and implicit classes
値クラスとimplicit クラスで振る舞いを追加する
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 ... } }
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 ... } }
Fast at runtime, tooval graph: Graph[N, E] = ...if(graph.isCyclic) sys.error("O NOES")
val graph: Graph[N, E] = ...if(Graph.Ops.isCyclic(graph)) sys.error("O NOES")
Translates to static helper method call
実行時には static メソッドの呼び出しへと変換される
Cheat in an EmergencyWith Dynamic Types
いざという時の動的型
class MapHelper(json: Map[String,AnyRef]) extends Dynamic {
def selectDynamic(name: String) = (json get name getOrElse sys.error(s"Attribute $name not found in json: $json"))
}
scala> val m = new MapHelper(Map[String,AnyRef]("name" -> "Jimmy", "age" -> "10"))m: MapHelper = MapHelper@683f67e0
scala> m.nameres1: AnyRef = Jimmy
scala> m.sexjava.lang.RuntimeException: Attribute sex not found in json: Map(name -> Jimmy, age -> 10)
Promise the Future!Make sure to deliver
Promise とFuture (約束は守りましょう)
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))
Why not Java Futures?
executor.submit(new Callable<Integer>() { def call(): Integer = { Thread sleep 3000L new Integer(5) }})
future { Thread sleep 30000L 5}
Creating!
Why not Java Futures?
val x: Future[Integer] = ...
x.get(10, TimeUnit.SECONDS)
val x: Future[Int] = ...
Await.result(x, 10 seconds)
Blocking!
Why not Java Futures?
N/Aval x: Future[Int] = ...val y: Future[Int] = x map { result => result + 5 }
Non-Blocking
chains!
Scala's FuturesProvide a lightweight model for asynchronous, non-blocking execution that can be chained and joined throughout your application.
Future: 軽量な非同期・ノンブロッキング実行モデル
trait AsynchService { def users: Future[Seq[User]] def projects(user: User):Future[Seq[Project]]}
def allprojects(api: AsynchService): Future[Set[Project]] = (Future.traverse(api.users)(api.projects) map (_.flatten.toSet))
Traverse is fork joindef traverse[A]( seq: Future[Seq[A]] )( op: A => Future[B] ): Future[Seq[B]] = ....
traverse は fork/join を用いて行われる
Feeling Crazy?Manipulate some ASTs
ちょっと遊ぶ?AST をいじろう
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(())}
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 user sees
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
Tree Transformationobject Bar { assert(false, "THIS IS A BAD OBJECT")}
構文木の変換
object Bar {
} Expr[Boolean]Expr[Any]
object Bar {
} Expr[Boolean]Expr[Any]
Macro
object Bar {
}Expr[Unit] Macro
object Bar { ()
}
A Brave New WorldWelcome to
すばらしい新世界へようこそ
What's 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
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
Questions?
質問ある?