Introducing 

Prezi AI.

Your new presentation assistant.

Refine, enhance, and tailor your content, source relevant images, and edit visuals quicker than ever before.

Loading…
Transcript

println("Yeah")

class User(val name: String)

From Scala to JavaScript

Scala

Object Oriented

Println

Initial Program

General purpose, statically typed language on the JVM

StringConcat

trait MyProgram extends JsScala {

def main(name: Rep[String]): Rep[Unit] = {

println("Hello " + name + "!")

}

}

Const

StringConcat

object Main {

def main(args: Array[String]) {

println("Hello, World!")

}

}

class Greeter(name: String) {

def greet() {

println(s"Hello, $name!")

}

}

new Greeter("Julien").greet()

Basics

"!"

Const

name

Tiark Rompf, Martin Odersky: Lightweight Modular Staging end Embedded Compilers: Abstraction without Regret for High-Level High-Performance Programming. EPFL, Lausanne, 2012.

Grzegorz Kossakowski, Nada Amin, Tiark Rompf, Martin Odersky: JavaScript as an Embedded DSL. ECOOP 2012.

"Hello "

Functional Programming

Just Great

Code Generator

Generated Code

trait SuperHero extends Person with Flying

with Swimming with Running

trait Functor[F[_]] {

def fmap[A, B](f: A => B): F[A] => F[B]

}

var main = function (x0) {

var x1 = "Hello, " + x0;

var x2 = x1 + "!";

console.log(x2);

};

val greet = (name: String) =>

s"Hello, $name!"

val greets = for {

name <- List("Peter", "John", "Bill")

} yield greet(name)

greets.foreach(println)

val prog = new MyProgram with JsScalaExp

val jsGen = new JSGenJsScala {

val IR: prog.type = prog

}

jsGen.emitSource(prog.main, "main", out)

higher-order type constructors

modules

extensible syntax

“for” notation

dependent types

algebraic datatypes

pattern matching

DOM Events

def on(e: EventDef)(handler: Rep[e.Data] => Rep[Unit]): Rep[Unit]

window.addEventListener('click', function (e) {

console.log(e.offsetX);

});

object Click extends EventDef {

type Data = MouseEvent

}

window.on(Click) { e =>

println(e.offsetX)

}

window.on(KeyUp) { e =>

println(e.keyCode) // Ok

println(e.offsetX) // Compile Error

}

window.addEventListener('clik', function (e) {

console.log(e.offetX);

});

Escaping from the Callback-Hell

Handling Null Values

$.get("/foo").then(function (foo) {

$.get("/bar/" + foo).then(function (bar) {

$.get("/baz/" + bar).done(function (baz) {

console.log(baz);

});

});

});

var form = document.querySelector('form.login');

if (form !== null) {

var pwd = form.querySelector('input[name=pwd]');

if (pwd !== null) {

console.log(pwd.value);

}

}

for {

foo <- Ajax.get("/foo")

bar <- Ajax.get("/bar/" + foo)

baz <- Ajax.get("/baz/" + bar)

} println(baz)

for {

form <- document.find("form.login")

pwd <- form.find("input[name=pwd]")

} println(pwd.value)

Building DOM Fragments

Repairing JavaScript and Browser APIs

<div class=article>

<span>{ article.name + ": " }</span>

<strong>{ article.price }</strong>

</div>

el('ul) {

for (article <- articles) yield {

el('li)(articleUi(article))

}

}

var articleUi = function (article) {

var div = document.createElement('div');

div.setAttribute('class', 'article');

var span = document.createElement('span');

var name = document.createTextNode(article.name + ': ');

span.appendChild(name);

div.appendChild(span);

var strong = document.createElement('strong');

var price = document.createTextNode(article.price);

strong.appendChild(price);

div.appendChild(strong);

return div

};

<ul>

<li><div class=article>…</div></li>

<li><div class=article>…</div></li>

</ul>

def articleUi(article: Rep[Article]) =

el('div, 'class -> 'article) {

el('span)(article.name + ": "),

el('strong)(article.price)

}

<div class=article>

<span>{ article.name + ": " }</span>

<strong>{ article.price }</strong>

</div>

Ad-hoc Polymorphism

def list[A : El](as: Rep[List[A]]) =

el('ul)(

for (a <- as) yield {

el('li)(implicitly[El[A]].el(a))

}

)

case class El[A](el: Rep[A => Node])

implicit val articleEl = El[Article] { (article: Rep[Article]) =>

el('div)(…)

}

implicit val userEl = El[User] { (user: Rep[User]) =>

el('span)(…)

}

programming language

library

programming

language

library

programming

language

generator

JavaScript

Scala

JavaScript

Scala

JavaScript

Scala

e.g. OPA, Links.

e.g. GWT, Kotlin, ClojureScript, Fay, etc.

Sharing Abstractions between Server and Client Sides

Building DOM Fragments

Form Validation Rules

Business Logic

val hello = el('div)("Hello, World!")

Form(single("age" -> number(min = 18)))

def connections(vertex: Rep[Vertex], edges: Rep[List[Edge]]) =

for {

edge <- edges

if edge.orig == vertex || edge.end == vertex

} yield {

if (edge.orig == vertex) edge.end

else edge.orig

}

var hello = document.createElement('div');

hello.appendChild(

document.createTextNode('Hello, World!')

);

$(function () {

$('#form').validate({

age: { min: 18 }

});

});

val hello = <div>Hello, World!</div>

Web Programming in Scala using js-scala

var connections = function (vertex, edges) {

return edges.filter(function (edge) {

return edge.orig == vertex || edge.end == vertex

}).map(function (edge) {

if (edge.orig == vertex) return edge.end

else return edge.orig

})

};

Un-inverting the Control of Callback-Driven APIs

val wheels = domEvents(MouseWheel)

val deltaYs = wheels map (_.wheelDeltaY)

for (deltaY <- deltaYs) println(deltaY)

var wheels = function (callback) {

window.addEventListener('mousewheel', function (e) {

callback(e);

});

};

var deltaYs = function (callback) {

return wheels(function (e) {

return callback(e.wheelDeltaY)

});

};

deltaYs.foreach(function (deltaY) {

console.log(deltaY);

});

implicit class EventsOps[A](as: Rep[Events[A]]) {

def map[B](f: Rep[A] => Rep[B]) = Events[B] { g =>

as((a: Rep[A]) => g(f(a)))

}

}

Julien Richard-Foy, Zenexity & INRIA, Université de Rennes 1, France

Immutable Programming Model

Scala as a Preprocessor

val inc = for {

n <- get[Int]

_ <- put(n + 1)

} yield n

println(inc(0)) // { value: 0, state: 1 }

VarNew

Block

Println

VarRead

Tuple2

Add

VarAssign

VarRead

val inc = get[Int].flatMap { n =>

put(n + 1).map { _ =>

n

}

}

Const(1)

Immutable Programming Model

var s = 0;

var n = s; // get

s = n + 1; // put

var result = { value: n, state: s };

console.log(result);

Reifying Data Type Definitions

def makeUser(name: Rep[String]) = {

new User(name) // Compile error

}

def printUser(user: Rep[User]) = {

println(user.name) // Compile error

}

Remaining Challenges

Macros to the rescue

Manual Data Type Reification

val either =

data("Either[+A, +B] = Left(a: A) | Right(b: B)")

case class User(name: String)

object User extends rep[User]

class User

def User(name: Rep[String]): Rep[User] =

record[User]("name" -> name)

implicit class UserOps(user: Rep[User]) {

def name: Rep[String] =

select[String](user, "name")

// define more methods here

}

def makeUser(name: Rep[String]): Rep[User] = {

User(name) // Ok

}

def printUser(user: Rep[User]) = {

println(user.name) // Ok

}

import either._

val intOrStr: Rep[Either[Int, String]] = Left(42)

intOrStr match {

case Left(a) => "it’s an Int: " + a,

case Right(b) => "it’s a String: " + b

}

intOrStr == Left(42) // true

Support all algebraic data types features

- structural equals

- pattern matching / folds

Js-Scala

repair browser’s APIs

expressive

Questions?

Let me try it!

http://github.com/js-scala

statically typed

share abstractions between servers and clients

Println

Const

"Yeah"

interpreter

Learn more about creating dynamic, engaging presentations with Prezi