JscexWrite Sexy JavaScript    Zhao Jie - SNDA - May 2011
About Me•       /       / Jeffrey Zhao /• Programmer• Blogger - http://blog.zhaojie.me/• Twitter: @jeffz_cn• F#, JavaScrip...
What’s Jscex• JavaScript Computation EXpression• A JavaScript language extension to help  programming in common scenarios•...
What’s NOT Jscex• Another language  •   Jscex is 100% JavaScript• A framework  •   It’s a library, works with any librarie...
Taste a Bit
Bubble Sortvar compare = function (x, y) {    return x - y;}var swap = function (a, i, j) {    var t = a[x]; a[x] = a[y]; ...
Animate it!var compare = function (x, y, callback) {         var innerLoop = function (array, x, y, callback) {    setTime...
Animate it!                                                                             at?var compare = function (x, y, c...
Bubble Sort Animationvar compareAsync = eval(Jscex.compile("async", function (x, y) {     $await(Jscex.Async.sleep(10)); /...
Bubble Sort Animationvar compareAsync = eval(Jscex.compile("async", function (x, y) {     $await(Jscex.Async.sleep(10)); /...
Design Principle #1
Keep Everything forJavaScript Programmer• Language features• Language semantics• Programming experiences
Language Features• Support almost all JavaScript constructs  •   Loops: while / for / for...in / do  •   Conditions: if / ...
Language Semantics• Keep all semantics as JavaScript• Explicit “bind” operations (like $await)  •   The only extension to ...
Programming          Experiences• Write, execute, debug as JavaScript• Modify and take effects immediately• No extra compi...
Async Programming is      Difficult
Code Locality is           Broken• Used to expressing algorithms linearly• Async requires logical division of algorithms• ...
Asynchronous Function // use async builder to execute the compiled code var somethingAsync = eval(Jscex.compile("async",  ...
React!!!function () {    var res = $await(<async work>);}
React!!!function () {    var res = $await(<async work>);}      an HTTP Request          an UI Event       a Timer Callback...
function () {          var img = $await(readAsync("http://..."));          console.log("loaded!");          $await(writeAs...
Work with Expressvar app = express.createServer();app.get(/, function (req, res) {    /**     * Question: How to do async ...
app.getAsync(/, eval(Jscex.compile("async", function (req, res) {    var keys = $await(db.getKeysAsync(...));    var resul...
I/O Parallelism• Software is often I/O bound •   Leveraging web services •   Working with data on disk• Network and disk s...
Make Things Parallelvar getDataAsync = eval(Jscex.compile("async", function (key) {     var res = $await(cache.getAsync(ke...
Task Model• Async library use a simple task model  •   Easy to write bindings for async operations  •   Parallel: $await(J...
AdvancedAsync Patterns
The Limitation ofCallback-based Model// if the sequence of processing is important, how to keep it?var i = 1;conn.onAsync(...
Erlang-like Agentvar i = 0;var agent = Agent.start(eval(Jscex.compile("async", function (mailbox) {    var id = i++;    va...
Jscex Components
Language & Libraries• Compiler (language extension)  •   JIT: generate code at runtime (development)  •   AOT: generate co...
AOT Compiler// before AOT compilationAgent.start(eval(Jscex.compile("async", function (mailbox) {    ...})));// after AOT ...
Jscex Builders• Compiler generates code into standard  patterns with a builder (name) •   A builder defines its name of the...
Not only for Async// infinite fibonacci sequencevar fib = eval(Jscex.compile("seq", function () {    var i = 0, j = 1;    ...
... and Maybe Monadvar maybeFunc = function () {    var maybeA = getA();    if (maybeA == Maybe.None) return Maybe.None;	 ...
Jscex Internals
Performance• Function has “linear” and “async” parts  •   Linear part: compiler keeps linear codes as much as      possibl...
Code Generation        Patterns• Code generation is direct and simple •   Map to original code easily •   Easy to debug: u...
Debug Browser Scripts
Debug Node.js Scripts
Try it NOW• Release under BSD license• https://github.com/JeffreyZhao/jecex
Q &A
Thanks
Upcoming SlideShare
Loading in...5
×

Jscex: Write Sexy JavaScript

9,803

Published on

Published in: Technology, Business
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
9,803
On Slideshare
0
From Embeds
0
Number of Embeds
11
Actions
Shares
0
Downloads
61
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Jscex: Write Sexy JavaScript

  1. 1. JscexWrite Sexy JavaScript Zhao Jie - SNDA - May 2011
  2. 2. 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
  3. 3. 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
  4. 4. 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
  5. 5. Taste a Bit
  6. 6. 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); } } }}
  7. 7. Animate it!var compare = function (x, y, callback) { var innerLoop = function (array, x, y, callback) { setTimeout(10, function () { if (y < array.length - x) { callback(x - y); compare(array[y], array[y + 1], function (r) { }); if (r > 0) {} swap(array, y, y + 1, function () { innerLoop(array, x, y + 1, callback);var swap = function (a, i, j, callback) { }); var t = a[x]; a[x] = a[y]; a[y] = t; } else { repaint(a); innerLoop(array, x, y + 1, callback); } setTimeout(20, callback); });} } else { callback();var outerLoop = function (array, x, callback) { } if (x < array) { } innerLoop(array, x, 0, function () { outerLoop(array, x + 1, callback); outerLoop(array, 0, function () { }); console.log("done!"); } else { }); callback(); }}
  8. 8. Animate it! at?var compare = function (x, y, callback) { th var innerLoop = function (array, x, y, callback) { is setTimeout(10, function () { if (y < array.length - x) { callback(x - y); compare(array[y], array[y + 1], function (r) { ll }); if (r > 0) {} swap(array, y, y + 1, function () { e innerLoop(array, x, y + 1, callback); hvar swap = function (a, i, j, callback) { }); var t = a[x]; a[x] = a[y]; a[y] = t; } else { e repaint(a); innerLoop(array, x, y + 1, callback); h } t setTimeout(20, callback); }); t} } else { a callback(); hvar outerLoop = function (array, x, callback) { } if (x < array) { } innerLoop(array, x, 0, function () { W outerLoop(array, x + 1, callback); outerLoop(array, 0, function () { }); console.log("done!"); } else { }); callback(); }}
  9. 9. 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)); } }}));
  10. 10. 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)); } }}));
  11. 11. Design Principle #1
  12. 12. Keep Everything forJavaScript Programmer• Language features• Language semantics• Programming experiences
  13. 13. 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 statement • break / continue to label • conditional break in switch statement• Nested functions
  14. 14. 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”
  15. 15. Programming Experiences• Write, execute, debug as JavaScript• Modify and take effects immediately• No extra compilation process • Code generation by JIT compiler as code runs
  16. 16. Async Programming is Difficult
  17. 17. 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
  18. 18. Asynchronous Function // use async builder to execute the compiled code var somethingAsync = eval(Jscex.compile("async", function (...) { // implementation } ));
  19. 19. React!!!function () { var res = $await(<async work>);}
  20. 20. React!!!function () { var res = $await(<async work>);} an HTTP Request an UI Event a Timer Callback a Query Response a Web Service Response an Agent Message
  21. 21. 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(); }); }); }) );})
  22. 22. 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);
  23. 23. 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));})));
  24. 24. 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
  25. 25. 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));})));
  26. 26. 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);
  27. 27. AdvancedAsync Patterns
  28. 28. The Limitation ofCallback-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 **/})));
  29. 29. Erlang-like Agentvar 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);});
  30. 30. Jscex Components
  31. 31. 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...
  32. 32. 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, ... );}));
  33. 33. 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
  34. 34. 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);}
  35. 35. ... 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;}));
  36. 36. Jscex Internals
  37. 37. 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
  38. 38. 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
  39. 39. Debug Browser Scripts
  40. 40. Debug Node.js Scripts
  41. 41. Try it NOW• Release under BSD license• https://github.com/JeffreyZhao/jecex
  42. 42. Q &A
  43. 43. Thanks
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×