Пишем на Scala для браузера

Gleb Kanterov

gleb@kanterov.ru

ScalaJS

JavaScript

ScalaJS

> ["10", "10", "10", "10"]
> .map(parseInt)
[10, NaN, 2, 3] 
> List("10", "10", "10", "10")
> .map(parseInt)
List(10, 10, 10, 10)

scala-js-dom

def main(div: html.Div) = {
  val child = dom.document
    .createElement("div")

  child.textContent =
    "Hi from Scala-js-dom"

  div.appendChild(child)
}

scalacss

val myStyle = style(
  margin(12 px, auto),

  &.hover(
    cursor.zoomIn
  ),

  &(media.not.handheld.landscape.maxWidth(640 px))(
    width(400 px)
  )
)

val button = style(
  addClassNames("btn", "btn-default"),
  textAlign.center
)

autowire

trait Api {
  def order(itemIds: List[Int]): Order
  def submit(order: Order): Unit
}

val client = Ajax[Api]

val z: Future[Unit] = for {
  order  <- client.order(itemIds).call()
  result <- client.submit(order).call()
} yield result

scala-async

val z: Future[Unit] = async {
  val order = await(client.order(itemIds).call())
  val result = await(client.submit(order).call())
  result
}

scala-js-react

@scalax
def render(self: This) = {
  val todo = self.state.todos.count(!_.completed)
  <section id="todoapp">
    <header id="header">
      <h1>todos</h1>
      <input id="new-todo"
             onChange={self.onChange}
             onKeyUp={self.onKeyPress}
             value={self.state.text}
             placeholder="What needs to be done?"
             autofocus={true}></input>
    </header>
  </section>
}

scodec

case class Person(name: String, title: String)

object Person {
  implicit val codec = Codec[Person]
}

sealed trait Tree
case class Node(l: Tree, r: Tree) extends Tree
case class Leaf(n: Int) extends Tree

object Tree {
  implicit lazy val codec: Codec[Tree] = {
    discriminated[Tree]
      .by(uint8)
      .typecase2(0, int32.as[Leaf])
      .typecase2(1, lazily { (codec :: codec).as[Node] })
  }
}

scalacheck

property("reverse") = Prop.forAll { l: List[String] => 
  l.reverse.reverse == l 
}

property("fib") = Prop.forAll { i suchThat (_ > 2) =>
  fib(i) ?= fib(i - 1) + fib(i - 2)
}

И другие

  • scalaz
  • scalaz-stream, scala.rx, monifu
  • shapeless
  • parboiled2
  • papa carlo
  • banana-rdf
  • scalajs-jquery
  • scalajs-angular
  • utest, minitest

А также

  • поддержка IDE
  • инкрементальная компиляция
  • source maps
  • Google Closure Compiler
  • размеры JS
    • минимум - 100 Кб
    • TODO MVC - 250 Кб (64 Kb gzip) + react
    • максимум - 1Mb

Заключение

  • Можно скомпилировать Scala в JS
  • Scala код можно звать из JS, и наоборот
  • Производительность сопоставима с JS
  • Есть много библиотек
  • Можно все написать на ScalaJS :)
  • Есть альтернативы, см. Haskell, Erlang, Clojure

Конец

Made with Slides.com