jscex: write sexy javascript

43

Click here to load reader

Upload: jeffz

Post on 06-May-2015

9.711 views

Category:

Technology


4 download

TRANSCRIPT

Page 1: Jscex: Write Sexy JavaScript

JscexWrite Sexy JavaScript

Zhao Jie - SNDA - May 2011

Page 2: Jscex: Write Sexy JavaScript

About Me

• 赵劼 / 老赵 / Jeffrey Zhao / 赵姐夫

• Programmer

• Blogger - http://blog.zhaojie.me/

• Twitter: @jeffz_cn

• F#, JavaScript, Scala, C#, Python, .NET, Mono...

• Java (as a language) hater

Page 3: Jscex: Write Sexy JavaScript

What’s Jscex

• JavaScript Computation EXpression

• A JavaScript language extension to help programming in common scenarios

• A port of F# Computation Expression• Inspired by the idea

• Design for JavaScript

Page 4: Jscex: Write Sexy JavaScript

What’s NOT Jscex

• Another language• Jscex is 100% JavaScript

• A framework• It’s a library, works with any libraries / frameworks

• A JavaScript engine / runtime• Execute in any ECMAScript 3 engines

Page 5: Jscex: Write Sexy JavaScript

Taste a Bit

Page 6: Jscex: Write Sexy JavaScript

Bubble Sortvar compare = function (x, y) { return x - y; }

var swap = function (a, i, j) { var t = a[x]; a[x] = a[y]; a[y] = t;}

var bubbleSort = function (array) { for (var x = 0; x < array.length; x++) { for (var y = 0; y < array.length - x; y++) { if (compare(array[y], array[y + 1]) > 0) { swap(array, y, y + 1); } } }}

Page 7: Jscex: Write Sexy JavaScript

Animate it!var compare = function (x, y, callback) { setTimeout(10, function () { callback(x - y); });}

var swap = function (a, i, j, callback) { var t = a[x]; a[x] = a[y]; a[y] = t; repaint(a); setTimeout(20, callback);}

var outerLoop = function (array, x, callback) { if (x < array) { innerLoop(array, x, 0, function () { outerLoop(array, x + 1, callback); }); } else { callback(); }}

var innerLoop = function (array, x, y, callback) { if (y < array.length - x) { compare(array[y], array[y + 1], function (r) { if (r > 0) { swap(array, y, y + 1, function () { innerLoop(array, x, y + 1, callback); }); } else { innerLoop(array, x, y + 1, callback); } }); } else { callback(); }}

outerLoop(array, 0, function () { console.log("done!");});

Page 8: Jscex: Write Sexy JavaScript

Animate it!var compare = function (x, y, callback) { setTimeout(10, function () { callback(x - y); });}

var swap = function (a, i, j, callback) { var t = a[x]; a[x] = a[y]; a[y] = t; repaint(a); setTimeout(20, callback);}

var outerLoop = function (array, x, callback) { if (x < array) { innerLoop(array, x, 0, function () { outerLoop(array, x + 1, callback); }); } else { callback(); }}

var innerLoop = function (array, x, y, callback) { if (y < array.length - x) { compare(array[y], array[y + 1], function (r) { if (r > 0) { swap(array, y, y + 1, function () { innerLoop(array, x, y + 1, callback); }); } else { innerLoop(array, x, y + 1, callback); } }); } else { callback(); }}

outerLoop(array, 0, function () { console.log("done!");});What th

e hell is that?

Page 9: Jscex: Write Sexy JavaScript

Bubble Sort Animationvar compareAsync = eval(Jscex.compile("async", function (x, y) { $await(Jscex.Async.sleep(10)); // each "compare" takes 10 ms. return x - y;}));

var swapAsync = eval(Jscex.compile("async", function (a, x, y) { var t = a[x]; a[x] = a[y]; a[y] = t; // swap repaint(a); // repaint after each swap $await(Jscex.Async.sleep(20)); // each "swap" takes 20 ms.}));

var bubbleSortAsync = eval(Jscex.compile("async", function (array) { for (var x = 0; x < array.length; x++) { for (var y = 0; y < array.length - x; y++) { var r = $await(compareAsync(array[y], array[y + 1])); if (r > 0) $await(swapAsync(array, y, y + 1)); } }}));

Page 10: Jscex: Write Sexy JavaScript

Bubble Sort Animationvar compareAsync = eval(Jscex.compile("async", function (x, y) { $await(Jscex.Async.sleep(10)); // each "compare" takes 10 ms. return x - y;}));

var swapAsync = eval(Jscex.compile("async", function (a, x, y) { var t = a[x]; a[x] = a[y]; a[y] = t; // swap repaint(a); // repaint after each swap $await(Jscex.Async.sleep(20)); // each "swap" takes 20 ms.}));

var bubbleSortAsync = eval(Jscex.compile("async", function (array) { for (var x = 0; x < array.length; x++) { for (var y = 0; y < array.length - x; y++) { var r = $await(compareAsync(array[y], array[y + 1])); if (r > 0) $await(swapAsync(array, y, y + 1)); } }}));

Page 11: Jscex: Write Sexy JavaScript

Design Principle #1

Page 12: Jscex: Write Sexy JavaScript

Keep Everything for JavaScript Programmer

• Language features

• Language semantics

• Programming experiences

Page 13: Jscex: Write Sexy JavaScript

Language Features• Support almost all JavaScript constructs• Loops: while / for / for...in / do

• Conditions: if / switch

• Error handling: try...catch...finally

• Others: return / break / continue / throw

• Not supported• with block

• break / continue to label

• conditional break in switch block

• Nested functions

Page 14: Jscex: Write Sexy JavaScript

Language Semantics

• Keep all semantics as JavaScript

• Explicit “bind” operations (like $await)• The only extension to the language

• Act like a method call

• Make clear which operation is “special”

Page 15: Jscex: Write Sexy JavaScript

Programming Experiences

• Write, execute, debug as JavaScript

• Modify and take effects immediately

• No extra compilation process• Code generation by JIT compiler as code runs

Page 16: Jscex: Write Sexy JavaScript

Async Programming is Difficult

Page 17: Jscex: Write Sexy JavaScript

Code Locality is Broken

• Used to expressing algorithms linearly

• Async requires logical division of algorithms

• Very difficult to• Combine multiple asynchronous operations

• Deal with exceptions and cancellation

Page 18: Jscex: Write Sexy JavaScript

Asynchronous Function

// use async builder to execute the compiled codevar somethingAsync = eval(Jscex.compile("async", function (...) { // implementation }));

Page 19: Jscex: Write Sexy JavaScript

function () { var res = $await(<async work>);}

React!!!

Page 20: Jscex: Write Sexy JavaScript

function () { var res = $await(<async work>);}

React!!!

an HTTP Requestan UI Event

a Timer Callbacka Query Response

a Web Service Responsean Agent Message

Page 21: Jscex: Write Sexy JavaScript

function () { var img = $await(readAsync("http://...")); console.log("loaded!"); $await(writeAsync("./files/...")); console.log("saved!");}

=(function () { var _b_ = Jscex.builders["async"]; return _b_.Start(this, _b_.Delay(function () { _b_.Bind(readAsync(...), function (img) { console.log("loaded!"); return _b_.Bind(writeAsync(...), function () { console.log("saved!"); return _b_.Normal(); }); }); }) );})

Page 22: Jscex: Write Sexy JavaScript

Work with Expressvar app = express.createServer();

app.get('/', function (req, res) { /** * Question: How to do async work here? e.g.: * * 1. Get multiple keys from database. * 2. For each key, try get data from cache. * If cache missed, get data from database. * 3. Write a list of result to the response. * * Note: all "get" operations are asynchronous. **/});

app.listen(3000);

Page 23: Jscex: Write Sexy JavaScript

app.getAsync('/', eval(Jscex.compile("async", function (req, res) { var keys = $await(db.getKeysAsync(...)); var results = []; for (var i = 0; i < keys.length; i++) { var r = $await(cache.getAsync(keys[i])); if (!r) { r = $await(db.getAsync(keys[i])); }

results.push(r); } res.send(generateList(results));})));

Page 24: Jscex: Write Sexy JavaScript

I/O Parallelism

• Software is often I/O bound• Leveraging web services

• Working with data on disk

• Network and disk speeds increasing slower

• I/O resources are inherently parallel• Huge opportunity for performance

Page 25: Jscex: Write Sexy JavaScript

Make Things Parallelvar getDataAsync = eval(Jscex.compile("async", function (key) { var res = $await(cache.getAsync(key)); if (res) return res; return $await(db.getAsync(key));}));

app.getAsync('/', eval(Jscex.compile("async", function (req, res) { var keys = $await(db.getKeysAsync(...));

// get tasks of “get data” (not started yet) var tasks = keys.map(function (key) { return getDataAsync(key); });

// make requests in parallel var results = $await(Jscex.Async.parallel(tasks)); res.send(generateList(results));})));

Page 26: Jscex: Write Sexy JavaScript

Task Model• Async library use a simple task model• Easy to write bindings for async operations

• Parallel: $await(Jscex.Async.parallel(taskA, taskB))

• Series: $await(taskA.continueWith(taskB))

• The semantics of $await: wait a task to complete• Start the task if it’s not running

• Return immediately if it’s already completed

• We can start a task manually (if necessary)• E.g. taskA.start(); $await(taskB); $await(taskA);

Page 27: Jscex: Write Sexy JavaScript

AdvancedAsync Patterns

Page 28: Jscex: Write Sexy JavaScript

The Limitation of Callback-based Model// if the sequence of processing is important, how to keep it?var i = 1;conn.onAsync("data", eval(Jscex.compile("async", function () { var id = i++;

$await(step1); console.log("step 1 - request " + id); $await(step2); console.log("step 2 - request " + id); /** * A possible sequence (which is unacceptable): * step 1 - request 1 * step 1 - request 2 * step 2 - request 2 * step 2 - request 1 **/})));

Page 29: Jscex: Write Sexy JavaScript

Erlang-like Agent

var i = 0;var agent = Agent.start(eval(Jscex.compile("async", function (mailbox) { var id = i++;

var msg = $await(mailbox.receive()); $await(step1); console.log("step 1 - request " + id); $await(step2); console.log("step 2 - request " + id);})));

conn.on("data", function (data) { // data would be queued in mailbox agent.send(data);});

Page 30: Jscex: Write Sexy JavaScript

Jscex Components

Page 31: Jscex: Write Sexy JavaScript

Language & Libraries

• Compiler (language extension)• JIT: generate code at runtime (development)

• AOT: generate code before runtime (production)

• Builders (libraries)• Async: simplfied async programming

• Sequense: generator for lazy iterator (Py, C#, JS 1.7)

• more...

Page 32: Jscex: Write Sexy JavaScript

AOT Compiler// before AOT compilationAgent.start(eval(Jscex.compile("async", function (mailbox) { ...})));

// after AOT compilation// independent of compiler scripts// need a tiny library only (3kb when gzipped)Agent.start((function (mailbox) { var _b_ = Jscex.builders["async"]; return _b_.Start(this, ... );}));

Page 33: Jscex: Write Sexy JavaScript

Jscex Builders

• Compiler generates code into standard patterns with a builder (name)• A builder defines its name of the “bind” operation

• Execute with the standard methods implemented in the builder

Page 34: Jscex: Write Sexy JavaScript

Not only for Async// infinite fibonacci sequencevar fib = eval(Jscex.compile("seq", function () { var i = 0, j = 1; while (true) { $yield(i); // the bind operation

var t = i; i = j; j += t; }}));

var iter = fib().skip(10).take(10);while (iter.moveNext()) { console.log(iter.current);}

Page 35: Jscex: Write Sexy JavaScript

... and Maybe Monadvar maybeFunc = function () { var maybeA = getA(); if (maybeA == Maybe.None) return Maybe.None;

var maybeB = getB(); if (maybeB == Maybe.None) return Maybe.None;

return maybeA.value + maybeB.value;}

// simplified versionvar maybeFunc = eval(Jscex.compile("maybe", function () { var a = $try(getA()); var b = $try(getB()); return a + b;}));

Page 36: Jscex: Write Sexy JavaScript

Jscex Internals

Page 37: Jscex: Write Sexy JavaScript

Performance

• Function has “linear” and “async” parts• Linear part: compiler keeps linear codes as much as

possible

• Async part: at the same level of hand-writing, callback-based implementation

• An async operation always takes much more time than a bunch of normal codes• Jscex never becomes a performance issue / bottleneck

Page 38: Jscex: Write Sexy JavaScript

Code Generation Patterns

• Code generation is direct and simple• Map to original code easily

• Easy to debug: use “debugger” statement to pause or add breakpoints in debuggers

• Based on standard methods• Start, Delay, Combine

• Loop, Try

• Normal, Return, Break, Continue, Throw

• Bind

Page 39: Jscex: Write Sexy JavaScript

Debug Browser Scripts

Page 40: Jscex: Write Sexy JavaScript

Debug Node.js Scripts

Page 41: Jscex: Write Sexy JavaScript

Try it NOW

• Release under BSD license

• https://github.com/JeffreyZhao/jscex

Page 42: Jscex: Write Sexy JavaScript

Q & A

Page 43: Jscex: Write Sexy JavaScript

Thanks