• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Jscex: Write Sexy JavaScript
 

Jscex: Write Sexy JavaScript

on

  • 10,076 views

 

Statistics

Views

Total Views
10,076
Views on SlideShare
4,867
Embed Views
5,209

Actions

Likes
3
Downloads
58
Comments
0

23 Embeds 5,209

http://www.cnblogs.com 3179
http://blog.zhaojie.me 1763
http://www.zuixiami.com 141
http://zhuaxia.com 27
http://xianguo.com 26
url_unknown 14
http://yuhushop.com 14
http://old.xianguo.com 10
http://www.slideshare.net 8
http://www.zhuaxia.com 6
http://www.oofeeds.com 4
http://cache.baidu.com 3
http://rssminer.net 2
http://www.newsblur.com 2
http://www.rsscolor.com 2
http://1.douyh.sinaapp.com 1
http://www.itfeed.cn 1
http://findex.cn 1
http://www.kismeto.com 1
http://feedly.com 1
http://newsblur.com 1
http://news.google.com 1
http://blog.zuixiami.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Jscex: Write Sexy JavaScript Jscex: Write Sexy JavaScript Presentation Transcript

    • JscexWrite Sexy JavaScript Zhao Jie - SNDA - May 2011
    • 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
    • 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
    • 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
    • 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]; 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); } } }}
    • 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(); }}
    • 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(); }}
    • 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)); } }}));
    • 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)); } }}));
    • 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 / 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
    • 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”
    • Programming Experiences• Write, execute, debug as JavaScript• Modify and take effects immediately• No extra compilation process • Code generation by JIT compiler as code runs
    • Async Programming is Difficult
    • 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
    • Asynchronous Function // use async builder to execute the compiled code var somethingAsync = eval(Jscex.compile("async", function (...) { // implementation } ));
    • React!!!function () { var res = $await(<async work>);}
    • 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
    • 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(); }); }); }) );})
    • 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);
    • 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));})));
    • 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
    • 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));})));
    • 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);
    • AdvancedAsync Patterns
    • 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 **/})));
    • 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);});
    • Jscex Components
    • 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...
    • 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, ... );}));
    • 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
    • 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);}
    • ... 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;}));
    • Jscex Internals
    • 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
    • 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
    • Debug Browser Scripts
    • Debug Node.js Scripts
    • Try it NOW• Release under BSD license• https://github.com/JeffreyZhao/jecex
    • Q &A
    • Thanks