SlideShare a Scribd company logo
Jscex
- 2011.10
•       /       / Jeffrey Zhao /

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

•         @

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

• JavaScript Computation EXpression
• JavaScript
• F#                      JavaScript
 •     “            ”
 •     JavaScript       JavaScript
Jscex

•
    •   Jscex              JavaScript

•
    •   Jscex                           /

• JavaScript           /
    •           ECMAScript 3
深入浅出Jscex
var compare = function (x, y) {
    return x - y;
}

var swap = function (a, i, j) {
    var t = a[i]; a[i] = a[j]; a[j] = 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);
            }
        }
    }
}
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[i]; a[i] = a[j]; a[j] = 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();
    }
}
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[i]; a[i] = a[j]; a[j] = t;                       } else {




                            D
    repaint(a);                                                    innerLoop(array, x, y + 1, callback);
                                                               }




                           M
    setTimeout(20, callback);                             });
}                                                     } else {



                         T
                                                          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();
    }
}
var 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, i, j) {
     var t = a[i]; a[i] = a[j]; a[j] = 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));
         }
     }
}));

                                http://files.zhaojie.me/jscex/samples/async/sorting-animations.html?bubble
var 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, i, j) {
     var t = a[i]; a[i] = a[j]; a[j] = 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));
         }
     }
}));
•
    •
    •
•
    •
    •
Jscex

//
var somethingAsync = eval(Jscex.compile("async",
    function (...) {
        //
    }
));
function () {
    var res = $await(<async work>);
}
function () {
    var res = $await(<async work>);
}

        HTTP
         UI


      Web Service
var f = eval(Jscex.compile("async", function () {
     var img = $await(readAsync("http://..."));
     console.log("loaded!");
     $await(writeAsync("./files/..."));
     console.log("saved!");
}));
…
var f = eval('(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();
                });
            });
        })
    );
})');
…
var f = (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();
                });
            });
        })
    );
});
Express
var app = express.createServer();

app.get('/', function (req, res) {
    /**
     *
     *
     * 1.
     * 2.
     *
     * 3.              res
     *
     *           “   ”
     **/
});

app.listen(3000);
Jscex
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.getItemAsync(keys[i]));
        }

        results.push(r);
    }

    res.send(generateList(results));
})));
I/O

•             I/O
    •   Web
    •
•
• I/O
    •
var getItemAsync = eval(Jscex.compile("async", function (key) {
     var res = $await(cache.getAsync(key));
     if (res) return res;
     return $await(db.getItemAsync(key));
}));

app.getAsync('/', eval(Jscex.compile("async", function (req, res) {

    var keys = $await(db.getKeysAsync(...));

    //    “       ”
    var tasks = keys.map(function (key) {
        return getItemAsync(key);
    });

    //
    var results = $await(Jscex.Async.parallel(tasks));

    res.send(generateList(results));
})));
•
    •
    •      $await(Jscex.Async.parallel(taskA, taskB))

    •      $await(taskA.continueWith(taskB))


• $await
    •
    •
•
    •      taskA.start(); $await(taskB); $await(taskA);
//
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);

    /**
      *
      *     step   1   -   request   1
      *     step   1   -   request   2
      *     step   2   -   request   2
      *     step   2   -   request   1
      **/
})));
... the principle we go by is, don't expect to see
a particular concurrency model put into C#
because there're many different concurrency
model ... it's more about finding things are
common to all kinds of concurrency ...

                              - Anders Hejlsberg
Erlang
var i = 0;
var agent = Agent.start(eval(Jscex.compile("async", function (mailbox) {
    while (true) {
        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) {
    //           mailbox
    agent.send(data);
});
Jscex

•       JavaScript
    •
    •
    •
•              “     ”
•                          JavaScript
    •            while / for / for...in / do
    •            if / switch
    •                 try...catch...finally
    •            return / break / continue / throw

•
    •   with
    •              break continue
    •   switch                 break

•
//
var somethingAsync = eval(Jscex.compile("async",
    function (...) {
        //
    }
));
eval
Sample = {
    //
    compile: function (func) {
        return "(" + func.toString() + ")";
    },

    //    eval
    compileEx: function (func) {
        return eval("(" + func.toString() + ")");
    }
}
eval
(function () {
    var a = 1;

    // f1
    var f1 = eval(Sample.compile(function () {
         alert(a);
    }));
    f1(); //     “1”

    // f2         Sample.compileEx
    var f2 = Sample.compileEx(function () {
        alert(a);
    });
    f2(); //    “a      ”
})();
•                 JavaScript

•       “bind”                 $await
    •
    •         “          ”
    •     “        ”
•       JavaScript

•
•
    •                     JIT
    •        JavaScript
“               ”
MyClass.prototype = {
    get: function (n) {
        ...
    },

    calculateAsync: eval(Jscex.compile("async", function (n) {
        var numbers = [];
        for (var i = 0; i < n; i++)
        	 numbers.push(i);
        	
        this.result = $await(make(numbers));
    }))
}
“                 ”
MyClass.prototype = {
    get: function (n) {
        ...
    },                                Jscex
    calculateAsync: eval(Jscex.compile("async", function (n) {
        var numbers = [];
        for (var i = 0; i < n; i++)
        	 numbers.push(i);
        	
        this.result = $await(make(numbers));
    }))
}                            Jscex
Jscex vs.
•
•
    •   Virtual Panel: How to Survive Asynchronous
        Programming in JavaScript

•
    •   StratifiedJS
    •   Narrative JavaScript
    •   Streamline             Jscex
Jscex vs.
•
    •
    •
    •
• Jscex
    •     JavaScript
    •
    •
Jscex vs.
•
    •
    •
    •
• Jscex
    •       JavaScript
    •       JavaScript
    •       JavaScript
Streamline

•                Jscex
    •       JavaScript
    •                    JIT
    •
•       Jscex
    •
    •   Yield – Resume vs. Asynchronous Callbacks – An
        Equivalence
Streamline (input)

var bubbleSortAsync = function (array, _) {
    for (var x = 0; x < array.length; x++) {
        for (var y = 0; y < array.length - x; y++) {
            if (compareAsync(array[y], array[y + 1], _) > 0)
                swapAsync(array, y, y + 1, _);
        }
    }
}
Streamline (compiled)
var bubbleSortAsync = function __1(array, _) {
  if (!_) {
    return __future(__1, arguments, 1);
  }                                                        if ((y < (array.length - x))) {
;                                                             return compareAsync(array[y], array[(y + 1)], __cb(_, function(__0, r) {
  var __then = _;                                               if ((r > 0)) {
  var x = 0;                                                       return swapAsync(array, y, (y + 1), __cb(_, __then));
  var __4 = false;                                              }
  return function(__break) {                                  ;
    var __loop = __nt(_, function() {                           return __then();
      var __then = __loop;                                    }));
      if (__4) {                                           }
         x++;                                                else {
      }                                                       return __break();
        else {                                             }
         __4 = true;                                     ;
      }                                                  });
    ;                                                    return __loop();
      if ((x < array.length)) {                        }(__then);
         var y = 0;                                 }
         var __3 = false;                             else {
         return function(__break) {                    return __break();
           var __loop = __nt(_, function() {        }
              var __then = __loop;                ;
              if (__3) {                          });
                 y++;                             return __loop();
              }                                 }(__then);
                else {                       };
                 __3 = true;
              }
           ;




                                                                         http://sage.github.com/streamlinejs/examples/streamlineMe.html
Jecex (input)

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));
         }
     }
}));
Jecex (compiled)
var bubbleSortAsync = (function (array) {
    var _b_ = Jscex.builders["async"];
    return _b_.Start(this,
        _b_.Delay(function () {
            var x = 0;
            return _b_.Loop(
                function () { return x < array.length; },
                function () { x++; },
                _b_.Delay(function () {
                    var y = 0;
                    return _b_.Loop(
                        function () { return y < (array.length - x); },
                        function () { y++; }
                        _b_.Delay(function () {
                             return _b_.Bind(compareAsync(array[y], array[y + 1]), function (r) {
                                 if (r > 0) {
                                     return _b_.Bind(swapAsync(array, y, y + 1), function () {
                                          return _b_.Normal();
                                     });
                                 } else {
                                     return _b_.Normal();
                                 }
                             });
                        }),
                        false
                    );
                }),
                false
            );
        })
    );
})
Jecex (compiled)
            var bubbleSortAsync = (function (array) {
                var _b_ = Jscex.builders["async"];
                return _b_.Start(this,
                    _b_.Delay(function () {
                                                     outer loop
                        var x = 0;
                        return _b_.Loop(
                            function () { return x < array.length; },
                            function () { x++; },
                            _b_.Delay(function () {
                                var y = 0;
                                return _b_.Loop(

       inner loop                   function () { return y < (array.length - x); },
                                    function () { y++; }
                                    _b_.Delay(function () {
                                         return _b_.Bind(compareAsync(array[y], array[y + 1]), function (r) {
                                             if (r > 0) {
                                                 return _b_.Bind(swapAsync(array, y, y + 1), function () {

$await(compareAsync(...))                             return _b_.Normal();
                                                 });
                                             } else {                                $await(swapAsync(...))
                                                 return _b_.Normal();
                                             }
                                         });
                                    }),
                                    false
                                );
                            }),
                            false
                        );
                    })
                );
            })
Jscex
•
    •
    •                   “debugger”


•       JavaScript
    •   Start, Delay, Combine
    •   Loop, Try
    •   Normal, Return, Break, Continue, Throw
    •   Bind
深入浅出Jscex
Node.js
•
    •   JIT
    •   AOT

•
    •
    •                    Python C#
        JavaScript 1.7
    •         …
AOT
// AOT
Agent.start(eval(Jscex.compile("async", function (mailbox) {
    ...
})));

// AOT
//
//                   gzip     3kb
Agent.start((function (mailbox) {
     var _b_ = Jscex.builders["async"];
     return _b_.Start(this,
         ...
     );
}));
Jscex

•
    •           “   ”

•
//
var 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);
}
…                   Maybe Monad
var 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;
}

//
var maybeFunc = eval(Jscex.compile("maybe", function () {
     var a = $try(getA());
     var b = $try(getB());
     return a + b;
}));
•               “   ” “   ”
    •
    •
•
    •   Jscex       /
for                            Loop
function (urls) {
    for (var i = 0; i < urls.length; i++) {
        $await(requestAsync(urls[i]));
    }
}
for                                 Loop
function (urls) {
    for (var i = 0; i < urls.length; i++) {
        $await(requestAsync(urls[i]));
    }
}          function (urls) {
               var _b_ = Jscex.builders["async"];
               return _b_.Start(this,
                   _b_.Delay(function () {
                       var i = 0;
                       return _b_.Loop(
                           function () { return i < urls.length; },
                           function () { i++; },
                           _b_.Delay(function () {
                               return _b_.Bind(requestAsync(urls[i]), function () {
                                   return _b_.Normal();
                               });
                           }),
                           false
                       );
                   })
               );
           }
for
function (urls) {
    var requests = [];

    for (var i = 0; i < urls.length; i++) {
        requests.push(requestAsync(urls[i]));
    }

    $await(Jscex.Async.parallel(requests));
}
for
function (urls) {
    var requests = [];

    for (var i = 0; i < urls.length; i++) {
        requests.push(requestAsync(urls[i]));
    }
               function (urls) {
                   var _b_ = Jscex.builders["async"];
    $await(Jscex.Async.parallel(requests));
}                  return _b_.Start(this,
                       _b_.Delay(function () {

                              var requests = [];
                              for (var i = 0; i < urls.length; i++) {
                                  requests.push(requestAsync(urls[i]));
                              }

                              return _b_.Bind(Jscex.Async.parallel(requests), function () {
                                  return _b_.Normal();
                              });
                         })
                  );
              }
•       BSD

•
    •    https://github.com/JeffreyZhao/jscex
    •    http://www.sndacode.com/projects/jscex
Q &A
深入浅出Jscex

More Related Content

深入浅出Jscex

  • 2. / / Jeffrey Zhao / • • http://blog.zhaojie.me/ • @ • F#, JavaScript, Scala, C#, Python, .NET, Mono... • Java
  • 3. Jscex • JavaScript Computation EXpression • JavaScript • F# JavaScript • “ ” • JavaScript JavaScript
  • 4. Jscex • • Jscex JavaScript • • Jscex / • JavaScript / • ECMAScript 3
  • 6. var compare = function (x, y) { return x - y; } var swap = function (a, i, j) { var t = a[i]; a[i] = a[j]; a[j] = 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. 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[i]; a[i] = a[j]; a[j] = 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. 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[i]; a[i] = a[j]; a[j] = t; } else { D repaint(a); innerLoop(array, x, y + 1, callback); } M setTimeout(20, callback); }); } } else { T 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(); } }
  • 9. var 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, i, j) { var t = a[i]; a[i] = a[j]; a[j] = 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)); } } })); http://files.zhaojie.me/jscex/samples/async/sorting-animations.html?bubble
  • 10. var 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, i, j) { var t = a[i]; a[i] = a[j]; a[j] = 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. • • • • •
  • 12. Jscex // var somethingAsync = eval(Jscex.compile("async", function (...) { // } ));
  • 13. function () { var res = $await(<async work>); }
  • 14. function () { var res = $await(<async work>); } HTTP UI Web Service
  • 15. var f = eval(Jscex.compile("async", function () { var img = $await(readAsync("http://...")); console.log("loaded!"); $await(writeAsync("./files/...")); console.log("saved!"); }));
  • 16. … var f = eval('(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(); }); }); }) ); })');
  • 17. … var f = (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(); }); }); }) ); });
  • 18. Express var app = express.createServer(); app.get('/', function (req, res) { /** * * * 1. * 2. * * 3. res * * “ ” **/ }); app.listen(3000);
  • 19. Jscex 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.getItemAsync(keys[i])); } results.push(r); } res.send(generateList(results)); })));
  • 20. I/O • I/O • Web • • • I/O •
  • 21. var getItemAsync = eval(Jscex.compile("async", function (key) { var res = $await(cache.getAsync(key)); if (res) return res; return $await(db.getItemAsync(key)); })); app.getAsync('/', eval(Jscex.compile("async", function (req, res) { var keys = $await(db.getKeysAsync(...)); // “ ” var tasks = keys.map(function (key) { return getItemAsync(key); }); // var results = $await(Jscex.Async.parallel(tasks)); res.send(generateList(results)); })));
  • 22. • • $await(Jscex.Async.parallel(taskA, taskB)) • $await(taskA.continueWith(taskB)) • $await • • • • taskA.start(); $await(taskB); $await(taskA);
  • 23. // 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); /** * * step 1 - request 1 * step 1 - request 2 * step 2 - request 2 * step 2 - request 1 **/ })));
  • 24. ... the principle we go by is, don't expect to see a particular concurrency model put into C# because there're many different concurrency model ... it's more about finding things are common to all kinds of concurrency ... - Anders Hejlsberg
  • 25. Erlang var i = 0; var agent = Agent.start(eval(Jscex.compile("async", function (mailbox) { while (true) { 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) { // mailbox agent.send(data); });
  • 26. Jscex • JavaScript • • • • “ ”
  • 27. JavaScript • while / for / for...in / do • if / switch • try...catch...finally • return / break / continue / throw • • with • break continue • switch break •
  • 28. // var somethingAsync = eval(Jscex.compile("async", function (...) { // } ));
  • 29. eval Sample = { // compile: function (func) { return "(" + func.toString() + ")"; }, // eval compileEx: function (func) { return eval("(" + func.toString() + ")"); } }
  • 30. eval (function () { var a = 1; // f1 var f1 = eval(Sample.compile(function () { alert(a); })); f1(); // “1” // f2 Sample.compileEx var f2 = Sample.compileEx(function () { alert(a); }); f2(); // “a ” })();
  • 31. JavaScript • “bind” $await • • “ ” • “ ”
  • 32. JavaScript • • • JIT • JavaScript
  • 33. ” MyClass.prototype = { get: function (n) { ... }, calculateAsync: eval(Jscex.compile("async", function (n) { var numbers = []; for (var i = 0; i < n; i++) numbers.push(i); this.result = $await(make(numbers)); })) }
  • 34. ” MyClass.prototype = { get: function (n) { ... }, Jscex calculateAsync: eval(Jscex.compile("async", function (n) { var numbers = []; for (var i = 0; i < n; i++) numbers.push(i); this.result = $await(make(numbers)); })) } Jscex
  • 35. Jscex vs. • • • Virtual Panel: How to Survive Asynchronous Programming in JavaScript • • StratifiedJS • Narrative JavaScript • Streamline Jscex
  • 36. Jscex vs. • • • • • Jscex • JavaScript • •
  • 37. Jscex vs. • • • • • Jscex • JavaScript • JavaScript • JavaScript
  • 38. Streamline • Jscex • JavaScript • JIT • • Jscex • • Yield – Resume vs. Asynchronous Callbacks – An Equivalence
  • 39. Streamline (input) var bubbleSortAsync = function (array, _) { for (var x = 0; x < array.length; x++) { for (var y = 0; y < array.length - x; y++) { if (compareAsync(array[y], array[y + 1], _) > 0) swapAsync(array, y, y + 1, _); } } }
  • 40. Streamline (compiled) var bubbleSortAsync = function __1(array, _) { if (!_) { return __future(__1, arguments, 1); } if ((y < (array.length - x))) { ; return compareAsync(array[y], array[(y + 1)], __cb(_, function(__0, r) { var __then = _; if ((r > 0)) { var x = 0; return swapAsync(array, y, (y + 1), __cb(_, __then)); var __4 = false; } return function(__break) { ; var __loop = __nt(_, function() { return __then(); var __then = __loop; })); if (__4) { } x++; else { } return __break(); else { } __4 = true; ; } }); ; return __loop(); if ((x < array.length)) { }(__then); var y = 0; } var __3 = false; else { return function(__break) { return __break(); var __loop = __nt(_, function() { } var __then = __loop; ; if (__3) { }); y++; return __loop(); } }(__then); else { }; __3 = true; } ; http://sage.github.com/streamlinejs/examples/streamlineMe.html
  • 41. Jecex (input) 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)); } } }));
  • 42. Jecex (compiled) var bubbleSortAsync = (function (array) { var _b_ = Jscex.builders["async"]; return _b_.Start(this, _b_.Delay(function () { var x = 0; return _b_.Loop( function () { return x < array.length; }, function () { x++; }, _b_.Delay(function () { var y = 0; return _b_.Loop( function () { return y < (array.length - x); }, function () { y++; } _b_.Delay(function () { return _b_.Bind(compareAsync(array[y], array[y + 1]), function (r) { if (r > 0) { return _b_.Bind(swapAsync(array, y, y + 1), function () { return _b_.Normal(); }); } else { return _b_.Normal(); } }); }), false ); }), false ); }) ); })
  • 43. Jecex (compiled) var bubbleSortAsync = (function (array) { var _b_ = Jscex.builders["async"]; return _b_.Start(this, _b_.Delay(function () { outer loop var x = 0; return _b_.Loop( function () { return x < array.length; }, function () { x++; }, _b_.Delay(function () { var y = 0; return _b_.Loop( inner loop function () { return y < (array.length - x); }, function () { y++; } _b_.Delay(function () { return _b_.Bind(compareAsync(array[y], array[y + 1]), function (r) { if (r > 0) { return _b_.Bind(swapAsync(array, y, y + 1), function () { $await(compareAsync(...)) return _b_.Normal(); }); } else { $await(swapAsync(...)) return _b_.Normal(); } }); }), false ); }), false ); }) ); })
  • 44. Jscex • • • “debugger” • JavaScript • Start, Delay, Combine • Loop, Try • Normal, Return, Break, Continue, Throw • Bind
  • 47. • JIT • AOT • • • Python C# JavaScript 1.7 • …
  • 48. AOT // AOT Agent.start(eval(Jscex.compile("async", function (mailbox) { ... }))); // AOT // // gzip 3kb Agent.start((function (mailbox) { var _b_ = Jscex.builders["async"]; return _b_.Start(this, ... ); }));
  • 49. Jscex • • “ ” •
  • 50. // var 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); }
  • 51. Maybe Monad var 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; } // var maybeFunc = eval(Jscex.compile("maybe", function () { var a = $try(getA()); var b = $try(getB()); return a + b; }));
  • 52. “ ” “ ” • • • • Jscex /
  • 53. for Loop function (urls) { for (var i = 0; i < urls.length; i++) { $await(requestAsync(urls[i])); } }
  • 54. for Loop function (urls) { for (var i = 0; i < urls.length; i++) { $await(requestAsync(urls[i])); } } function (urls) { var _b_ = Jscex.builders["async"]; return _b_.Start(this, _b_.Delay(function () { var i = 0; return _b_.Loop( function () { return i < urls.length; }, function () { i++; }, _b_.Delay(function () { return _b_.Bind(requestAsync(urls[i]), function () { return _b_.Normal(); }); }), false ); }) ); }
  • 55. for function (urls) { var requests = []; for (var i = 0; i < urls.length; i++) { requests.push(requestAsync(urls[i])); } $await(Jscex.Async.parallel(requests)); }
  • 56. for function (urls) { var requests = []; for (var i = 0; i < urls.length; i++) { requests.push(requestAsync(urls[i])); } function (urls) { var _b_ = Jscex.builders["async"]; $await(Jscex.Async.parallel(requests)); } return _b_.Start(this, _b_.Delay(function () { var requests = []; for (var i = 0; i < urls.length; i++) { requests.push(requestAsync(urls[i])); } return _b_.Bind(Jscex.Async.parallel(requests), function () { return _b_.Normal(); }); }) ); }
  • 57. BSD • • https://github.com/JeffreyZhao/jscex • http://www.sndacode.com/projects/jscex
  • 58. Q &A