node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def...

59
node.js? done.scala! Implementing Scalable Async IO using Delimited Continuations Tiark Rompf, EPFL Saturday, June 4, 2011

Transcript of node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def...

Page 1: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

node.js?done.scala!Implementing Scalable Async IO using

Delimited Continuations

Tiark Rompf, EPFL

Saturday, June 4, 2011

Page 2: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

who has heard about node.js?

Saturday, June 4, 2011

Page 3: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

6/3/11 7:18 AMnode.js

Page 1 of 4http://nodejs.org/

Evented I/O for V8 JavaScript.

An example of a web server written in Node which responds with"Hello World" for every request.

var http = require('http');http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n');}).listen(1337, "127.0.0.1");console.log('Server running at http://127.0.0.1:1337/');

To run the server, put the code into a file example.js and executeit with the node program:

% node example.jsServer running at http://127.0.0.1:1337/

Here is an example of a simple TCP server which listens on port1337 and echoes whatever you send it:

var net = require('net');

var server = net.createServer(function (socket) { socket.write("Echo server\r\n"); socket.pipe(socket);});

DownloadChangeLogAboutv0.4.8 docs

WikiBlogCommunityDemoJobs

Hash InsightsChickRx

Saturday, June 4, 2011

Page 4: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

purely asynchronous

callback driven

no blocking operations

good scalability

Saturday, June 4, 2011

Page 5: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

6/3/11 7:22 AMGoogle Trends: erlang, node.js, clojure,

Page 1 of 1http://www.google.com/trends?q=erlang%2C+node.js%2C+clojure%2C&ctab=0&geo=all&date=all&sort=0

[email protected] | Signout

erlang, node.js, clojure,

Search Trends

Tip: Use commas to compare multiple search terms.

Searches Websites All regions All years

Scale is based on the average worldwide traffic of erlang in all years. Learn more

erlang 1.00 node.js 0.08 clojure 0.12

Rank by erlang

Scaling Large Projects With ErlangSlashdot - Jul 6 2008

The AZ of Programming Languages: ErlangComputerworld - Jun 16 2009

The AZ of Programming Languages: ClojureComputerworld - Aug 10 2009

Erlang Solutions, Ltd. and Basho Technologies, Inc. EnterBroad Partnership to Deliver Scalable, Fault TolerantApplications to a Global MarketCNNMoney.com - Mar 30 2010

Programming ClojureSlashdot - May 17 2010

Erlang and OTP in ActionSlashdot - Dec 8 2010

More news results »

Regions

1. Sweden

2. RussianFederation

3. SouthKorea

4. SouthAfrica

5. India

6. Singapore

7. Ukraine

8. Indonesia

9. China

10. Philippines

Cities

1. Goteborg,Sweden

2. Stockholm,Sweden

3.Moscow,RussianFederation

4. Beijing,China

5.SanFrancisco,CA, USA

6. Shanghai,China

7. Guangzhou,China

8. Seattle,WA, USA

9. Delhi, India

10. Bogota,Colombia

Languages

1. Swedish

2. Korean

3. Russian

4. Chinese

5. English

6. Indonesian

7. Danish

8. Hungarian

9. Japanese

10. German

Export this page as a CSV file

Google Trends provides insights into broad search patterns. Please keep in mind that several approximations areused when computing these results.

©2008 Google - Discuss - Terms of Use - Privacy Policy - Help

Saturday, June 4, 2011

Page 6: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

why would Scala programmers care?

Saturday, June 4, 2011

Page 7: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

#1: it’s about scalability

Saturday, June 4, 2011

Page 8: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

#2: no equivalent Scala libs

Saturday, June 4, 2011

Page 9: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

a little experiment: port it over to Scala!

Saturday, June 4, 2011

Page 10: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

done.scala

• a minimal scala port of node.js

• only net, http and supporting modules

• very incomplete (and not at all done!)

Saturday, June 4, 2011

Page 11: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

an interesting exercise:

JavaScript Scaladynamic language statically typed

Saturday, June 4, 2011

Page 12: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

• added type annotations in a few places

• helper classes for anonymous objects{ host: ‘google.com’, port: 80 }

• overloading, default arguments and varargs instead of dynamic typeof

quite smooth overall:

Saturday, June 4, 2011

Page 13: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

use Java NIO underneath

Saturday, June 4, 2011

Page 14: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}) res.end('Hello World\n')}).listen(8000, "127.0.0.1")console.log('server running')

http.createServer { (req, res) => res.writeHead(200, "Content-Type" -> "text/plain") res.end("Hello World\n")}.listen(8000, "127.0.0.1")println("server running")

JavaScript

Scala

Saturday, June 4, 2011

Page 15: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

now what?

Saturday, June 4, 2011

Page 16: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

node’s conscious choice:only callback-driven apis

but is it the right choice?

Saturday, June 4, 2011

Page 17: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

small examples are fine but does it scale?

Saturday, June 4, 2011

Page 18: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

println(“hello”)setTimeout(1000) {

println(“world”)}

Saturday, June 4, 2011

Page 19: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

println(“hello”)setTimeout(1000) {

println(“world”)}

hello<pause>world

Saturday, June 4, 2011

Page 20: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

setTimeout(1000) {println(“world”)

}println(“hello”)

Saturday, June 4, 2011

Page 21: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

setTimeout(1000) {println(“world”)

}println(“hello”)

hello<pause>world

Saturday, June 4, 2011

Page 22: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

for (x <- List(1,2,3) {setTimeout(1000) {

println(“found ” + x)}

}

Saturday, June 4, 2011

Page 23: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

for (x <- List(1,2,3) {setTimeout(1000) {

println(“found ” + x)}

}

<pause>found 1found 2found 3

Saturday, June 4, 2011

Page 24: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

try {setTimeout(1000) {

throw new Exception}

} catch {case e =>

println(“caught: ” + e)}

Saturday, June 4, 2011

Page 25: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

try {setTimeout(1000) {

throw new Exception}

} catch {case e =>

println(“caught: ” + e)}

?Saturday, June 4, 2011

Page 26: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

many things no longer work as expected

Saturday, June 4, 2011

Page 27: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

callback-driven programmingis really hard

Saturday, June 4, 2011

Page 28: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

val host = “http://search.twitter.com/”val query = “#scaladays”

http.get(host,80,“search.atom?q=”+query) { res => println(“STATUS:” + res.statusCode) res.onData { chunk => println(“BODY:” + chunk) } res.onEnd { println(“DONE”) }}

Saturday, June 4, 2011

Page 29: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

val host = “http://search.twitter.com/”val query = “#scaladays”

http.get(host,80,“search.atom?q=”+query) { res => println(“STATUS:” + res.statusCode) res.onData { chunk => println(“BODY:” + chunk) } res.onEnd { println(“DONE”) }}

STATUS: 400BODY: <data>BODY: <more data>DONE

Saturday, June 4, 2011

Page 30: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

val host = “http://search.twitter.com/”val queries = List(“#scala”,“#scaladays”, “@odersky”)

val results = for (q <- queries) yield { http.get(host,80,“search.atom?q=”+query) { res => ... }}

println(results)

Saturday, June 4, 2011

Page 31: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

val host = “http://search.twitter.com/”val queries = List(“#scala”,“#scaladays”, “@odersky”)

val results = for (q <- queries) yield { http.get(host,80,“search.atom?q=”+query) { res => ... }}

println(results)

List(ClientRequest, ClientRequest, ClientRequest)

Saturday, June 4, 2011

Page 32: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

can we do something about it?

Saturday, June 4, 2011

Page 33: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

execute asynchronously

program synchronously

Saturday, June 4, 2011

Page 34: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

scalac -P:continuations:enable

Saturday, June 4, 2011

Page 35: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

def foobar: Int @suspendable = shift { retrn: (Int=>Unit) => retrn(7)}

def abort: Unit @suspendable = shift { retrn: (Unit=>Unit) => // just don’t return...

}

reset {println(“A”)abortprintln(“B”)

}println(“C”)

Saturday, June 4, 2011

Page 36: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

def foobar: Int @suspendable = shift { retrn: (Int=>Unit) => retrn(7)}

def abort: Unit @suspendable = shift { retrn: (Unit=>Unit) => // just don’t return...

}

reset {println(“A”)abortprintln(“B”)

}println(“C”)

AC

Saturday, June 4, 2011

Page 37: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

def setTimeout(delay: Int)(callback: => Unit): Unit = ...

println(“hello”)setTimeout(1000) {

println(“world”)}

Saturday, June 4, 2011

Page 38: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

def setTimeout(delay: Int)(callback: => Unit): Unit = ...

println(“hello”)setTimeout(1000) {

println(“world”)}

hello<pause>world

Saturday, June 4, 2011

Page 39: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

def setTimeout(delay: Int)(callback: => Unit): Unit = ...

def sleep(delay: Int) = shift { retrn: (Unit=>Unit) => setTimeout {

retrn()}

}

println(“hello”)setTimeout(1000) {

println(“world”)}

println(“hello”)sleep(1000)println(“world”)

hello<pause>world

Saturday, June 4, 2011

Page 40: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

def setTimeout(delay: Int)(callback: => Unit): Unit = ...

def sleep(delay: Int) = shift { retrn: (Unit=>Unit) => setTimeout {

retrn()}

}

println(“hello”)setTimeout(1000) {

println(“world”)}

println(“hello”)sleep(1000)println(“world”)

hello<pause>world

hello<pause>world

Saturday, June 4, 2011

Page 41: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

http.get(...) { res => res.onData { chunk => println(“BODY:” + chunk) } res.onEnd { println(“DONE”) }}

Saturday, June 4, 2011

Page 42: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

http.get(...) { res => res.onData { chunk => println(“BODY:” + chunk) } res.onEnd { println(“DONE”) }}

val res = http.get(...)

for (chunk <- res.data) { println(“BODY:” + chunk)}

println(“DONE”)

Saturday, June 4, 2011

Page 43: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

http.get(...) { res => res.onData { chunk => println(“BODY:” + chunk) } res.onEnd { println(“DONE”) }}

val res = http.get(...)

for (chunk <- res.data) { println(“BODY:” + chunk)}

println(“DONE”)

def data = new { def foreach(yld: Buffer=>Unit) = shift { retrn: (Unit=>Unit) =>

onData(yld)onEnd(retrn)

}def mkString = {

val s = new StringBuilder; foreach(s+=_); s.result}

}Saturday, June 4, 2011

Page 44: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

val host = “http://search.twitter.com/”val queries = List(“#scala”,“#scaladays”, “@odersky”)

val results = for (q <- queries) yield {val res = http.get(host,80,“search.atom?q=”+query)val xml = XML.loadString(res.data.mkString)xml \ "entry" \ "title" text

}

println(results)

Saturday, June 4, 2011

Page 45: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

val host = “http://search.twitter.com/”val queries = List(“#scala”,“#scaladays”, “@odersky”)

val results = for (q <- queries) yield {val res = http.get(host,80,“search.atom?q=”+query)val xml = XML.loadString(res.data.mkString)xml \ "entry" \ "title" text

}

println(results)

<console>:11: error: no type parameters for method map: (f: (java.lang.String) => B)(implicit bf: scala.collection.generic.CanBuildFrom[List[java.lang.String],B,That])That exist so that it can be applied to arguments ((java.lang.String) => String @scala.util.continuations.cpsParam[Unit,Unit])

Saturday, June 4, 2011

Page 46: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

val host = “http://search.twitter.com/”val queries = List(“#scala”,“#scaladays”, “@odersky”)

val results = for (q <- queries.suspendable) yield {val res = http.get(host,80,“search.atom?q=”+query)val xml = XML.loadString(res.data.mkString)xml \ "entry" \ "title" text

}

println(results)

Saturday, June 4, 2011

Page 47: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

val host = “http://search.twitter.com/”val queries = List(“#scala”,“#scaladays”, “@odersky”)

val results = for (q <- queries.suspendable) yield {val res = http.get(host,80,“search.atom?q=”+query)val xml = XML.loadString(res.data.mkString)xml \ "entry" \ "title" text

}

println(results)

List(List(“#Scala highlighted in article from @TheEconomist on parallel programing and multicore: http://econ.st/jkGchu @typesafe”, ...), List(“There are so many great talks today at #scaladays; it's hard to decide which to attend!”, ...), List(“@odersky is there any info on Cascade up somewhere?”, ...))

Saturday, June 4, 2011

Page 48: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {

def foreach(yld: A => Unit @suspendable): Unit @suspendable = {val it = xs.iteratorwhile (it.hasNext) yld(it.next)

}def map[B, That](f: A => B @suspendable)

(implicit bf: CanBuildFrom[Repr, B, That]): That @suspendable = {val b = bf(xs.repr)foreach(x => b += f(x))b.result

}}

}

val results = for (q <- List(1,2,3).suspendable) yield {sleep(1000); println(“tick”)

}

Saturday, June 4, 2011

Page 49: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {

def foreach(yld: A => Unit @suspendable): Unit @suspendable = {val it = xs.iteratorwhile (it.hasNext) yld(it.next)

}def map[B, That](f: A => B @suspendable)

(implicit bf: CanBuildFrom[Repr, B, That]): That @suspendable = {val b = bf(xs.repr)foreach(x => b += f(x))b.result

}}

}<pause>tick<pause>tick<pause>tick

val results = for (q <- List(1,2,3).suspendable) yield {sleep(1000); println(“tick”)

}

Saturday, June 4, 2011

Page 50: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

val host = “http://search.twitter.com/”val queries = List(“#scala”,“#scaladays”, “@odersky”)

val results = for (q <- queries.suspendable) yield {println(“start ”+q)val res = http.get(host,80,“search.atom?q=”+query)val xml = XML.loadString(res.data.mkString)println(“done ”+q)xml \ "entry" \ "title" text

}

Saturday, June 4, 2011

Page 51: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

val host = “http://search.twitter.com/”val queries = List(“#scala”,“#scaladays”, “@odersky”)

val results = for (q <- queries.suspendable) yield {println(“start ”+q)val res = http.get(host,80,“search.atom?q=”+query)val xml = XML.loadString(res.data.mkString)println(“done ”+q)xml \ "entry" \ "title" text

}

start #scaladone #scalastart #scaladaysdone #scaladaysstart @oderskydone @odersky

Saturday, June 4, 2011

Page 52: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

def spawn(body: => Unit @suspendable) = {eventLoop.submitTask(() => reset(body))

}

class DataFlowCell[A] {private[this] var value: Option[A] = Noneprivate[this] var queue: List[A=>Unit] = Nil

def apply() = shift { retrn: (A=>Unit) =>value match {

case Option(v) => retrn(v)case None => queue ::= retrn

}}

def set(v: A) = value match {case Option(_) => assert(false, “can’t set value twice”)case None => value = Some(v); queue.foreach(f => spawn(f(v)))

}}

Saturday, June 4, 2011

Page 53: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

def future[A](body: => A @suspendable) = {val cell = new DataFlowCell[A]spawn { cell.set(body) }cell

}

def par[A,B](a: => A @suspendable)(b: => B @suspendable) = {val (u,v) = (future(a), future(b))(u(),v())

}

par { sleep(1000); println(“a”)

} { sleep(1000); println(“b”)

}println(“done”)

Saturday, June 4, 2011

Page 54: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

def future[A](body: => A @suspendable) = {val cell = new DataFlowCell[A]spawn { cell.set(body) }cell

}

def par[A,B](a: => A @suspendable)(b: => B @suspendable) = {val (u,v) = (future(a), future(b))(u(),v())

}

par { sleep(1000); println(“a”)

} { sleep(1000); println(“b”)

}println(“done”)

<pause>badone

Saturday, June 4, 2011

Page 55: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

implicit def richParIterable[A,Seq,Repr](xs: ParIterableLike[A,Seq,Repr]) = new {def suspendable = new {

def foreach(yld: A => Unit @suspendable): Unit @suspendable = {val futures = xs.seq.map(x => future(yld(x)) // sequential list of futuresfutures.suspendable.foreach(_.apply())

}def map[B, That](f: A => B @suspendable)(... bf ...): That @suspendable = {

val futures = xs.seq.map(x => future(yld(x))futures.suspendable.map(_.apply())

}}

}

val results = for (q <- List(1,2,3).par.suspendable) yield {sleep(1000); println(“tick”)

}println(“done”)

Saturday, June 4, 2011

Page 56: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

implicit def richParIterable[A,Seq,Repr](xs: ParIterableLike[A,Seq,Repr]) = new {def suspendable = new {

def foreach(yld: A => Unit @suspendable): Unit @suspendable = {val futures = xs.seq.map(x => future(yld(x)) // sequential list of futuresfutures.suspendable.foreach(_.apply())

}def map[B, That](f: A => B @suspendable)(... bf ...): That @suspendable = {

val futures = xs.seq.map(x => future(yld(x))futures.suspendable.map(_.apply())

}}

}

<pause>tickticktickdone

val results = for (q <- List(1,2,3).par.suspendable) yield {sleep(1000); println(“tick”)

}println(“done”)

Saturday, June 4, 2011

Page 57: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

val host = “http://search.twitter.com/”val queries = List(“#scala”,“#scaladays”, “@odersky”)

val results = for (q <- queries.par.suspendable) yield {println(“start ”+q)val res = http.get(host,80,“search.atom?q=”+query)val xml = XML.loadString(res.data.mkString)println(“done ”+q)xml \ "entry" \ "title" text

}

Saturday, June 4, 2011

Page 58: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

val host = “http://search.twitter.com/”val queries = List(“#scala”,“#scaladays”, “@odersky”)

val results = for (q <- queries.par.suspendable) yield {println(“start ”+q)val res = http.get(host,80,“search.atom?q=”+query)val xml = XML.loadString(res.data.mkString)println(“done ”+q)xml \ "entry" \ "title" text

}

start #scalastart #scaladaysstart @oderskydone #scaladone #scaladaysdone @odersky

Saturday, June 4, 2011

Page 59: node.js? done.scala!days2011.scala-lang.org/sites/days2011/files/56. node...implicit def richIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def suspendable = new {def foreach(yld:

Conclusions

• Scala needs good networking libs

• asynchronous execution does not meancallback-driven programming

• continuations can re-introduce synchronictiy

Saturday, June 4, 2011