-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 4/5/2010 10:26 AM, David Herman wrote: > [BTW, your quoted text got garbled.] > >> In order to utilize leverage continuations with a function that >> execute multiple we would need to eliminate single-shot >> restriction. You could then create some library function that >> passed the continuation to the setInterval function to do >> something like: var toggle = true; intervalling->(INTERVAL); >> elt.style.background =... > > Your answers keep leaving out the definition of the function that > you're calling via `->', which is supposed to be the part that > creates the requisite object with `continueWith' etc. Examples > don't do much good if they skip the part they were supposed to > illustrate! > >> But in this case, using the yielding call would be confusing and >> provide very little benefit. This is definitely not the type of >> scenario that it is designed for, normal anon functions work >> great here. This is geared for when a callback is used to execute >> the remainder of a sequence after the completion of an >> asynchronous that we see so often in JavaScript. > > I know. I wanted an example that had *both* asynchronous *and* > synchronous statements, to understand the control flow of your > proposal better, but I also was trying to keep it short. Maybe > you'd prefer this example, which more clearly separates the parts > that would be expressed with `->': > > function setup() { getThreeThings(URL1, URL2, URL3); alert("done > setup!"); } > > function getThreeThings(url1, url2, url3) { getAndFrob(url1); > getAndMunge(url2); getAndGrok(url3); } > > function getAndFrob(url) { var xhr = new SimpleXHR(url); > xhr.get(function(data) { window.setTimeout(function() { > frob(data); }, TIMEOUT); }); } > > function getAndMunge(url) { var xhr = new SimpleXHR(url); > xhr.get(function(data) { window.setTimeout(function() { > munge(data); }, TIMEOUT); }); } > > function getAndGrok(url) { var xhr = new SimpleXHR(url); > xhr.get(function(data) { window.setTimeout(function() { > grok(data); }, TIMEOUT); }); } > > Would you mind writing out how to express this program with your > proposal? I'm just trying to understand. If you can help me with > some examples I think I maybe able to help clarify your ideas. OK, here is some code: function setup() { getThreeThings->(URL1, URL2, URL3); alert("done setup!"); } function getThreeThings(url1, url2, url3) { getAndFrob->(url1); getAndMunge->(url2); getAndGrok->(url3); } function getAndFrob(url) { var xhr = new SimpleXHR(url); var data = xhr.get->(); sleep->(TIMEOUT); return frob(data); } Translated: function setup(){ var $result = getThreeThings(URL1, URL2, URL3); return $handleResult($result); function $handleResult($result){ if($result && typeof $result.continueWith === "function"){ var $waiting = true; return $result.continueWith(function($resumeNextFrame){ if($waiting){ $waiting = false; return $handleResult($resumeNextFrame()); } throw new Error("The stack can not be resumed again"); }); } else { // execute the continuation of the function alert("done setup!"); } } } function getThreeThings(url1, url2, url3) { var $codePointer = 0; var $result = getAndFrob(url1); return $handleResult($result); function $handleResult($result){ if($result && typeof $result.continueWith === "function"){ var $waiting = true; return $result.continueWith(function($resumeNextFrame){ if($waiting){ $waiting = false; return $handleResult($resumeNextFrame()); } throw new Error("The stack can not be resumed again"); }); } else { // execute the continuation of the function if($codePointer == 0){ $codePointer++; return $handleResult(getAndMunge(url2)); } if($codePointer == 1){ return $handleResult(getAndGrok(url3)); } } } } function getAndFrob(url) { var $codePointer = 0; var xhr = new SimpleXHR(url); var data = xhr.get(); return $handleResult(data); function $handleResult($result){ if($result && typeof $result.continueWith === "function"){ var $waiting = true; return $result.continueWith(function($resumeNextFrame){ if($waiting){ $waiting = false; return $handleResult($resumeNextFrame()); } throw new Error("The stack can not be resumed again"); }); } else { // execute the continuation of the function if($codePointer == 0){ $codePointer++; return $handleResult(sleep(INTERVAL)); } if($codePointer == 1){ return frob(data); } } } } getAndFrob, getAndMange, and getAndGrok are all basically the same. // very simple continuation implementation function Continuation(){ var resolvedValue; var bottomFrame = function(){ return resolvedValue; }; var continuation = { continueWith: function(next){ var nextFrame = bottomFrame; bottomFrame = function(){ return next(nextFrame); } return continuation; }, resume: function(value){ resolvedValue = value; bottomFrame(); } }; return continuation; } // sleep function that uses a continuation function sleep(ms){ var continuation = new Continuation(); setTimeout(function(){ continuation.resume(); }, ms); return continuation; } function SimpleXHR(url){ var xhr = new XMLHttpRequest(); return { get: function(){ var continuation = new Continuation(); xhr.open("GET", url); xhr.onload = continuation.resume; xhr.send(); return continuation; } }; } Also, if you want to see what this would look like with the "yield" keyword based alternative: var startCoroutine = simpleContinuationHandler; function setup() { yield getThreeThings(URL1, URL2, URL3); alert("done setup!"); } function getThreeThings(url1, url2, url3) { yield getAndFrob(url1); yield getAndMunge(url2); yield getAndGrok(url3); } /* Note these could be done in parralel with: function getThreeThings(url1, url2, url3) { var frobbed = getAndFrob(url1); var munged = getAndMunge(url2); var grokked = getAndGrok(url3); yield frobbed, yield munged, yield grokked; } */ function getAndFrob(url) { var xhr = new SimpleXHR(url); var data = yield xhr.get(); yield sleep(TIMEOUT); return frob(data); } ... Translated: function setup(){ var $pointer = 0; // used to keep track of where we are // create the controller var $controller = { suspended: true, resume: function(getValue){ var nextValue; if(getValue){ nextValue = getValue(); } if($pointer == 0){ // start of function $pointer++; // execute until the yield operator and return the value passed to yield return getThreeThings(URL1, URL2, URL3); } if($pointer == 1){ // continuation from the yield $pointer++; // continue execution until the return operator $controller.suspended = false; // no more yield, function is done alert("done setup!"); return; } if($pointer > 1){ throw new Error("Can not resume a function that has returned"); } } }; // call the startCoroutine function return startCoroutine($controller); } function getThreeThings(url1, url2, url3) { var $pointer = 0; // used to keep track of where we are // create the controller var $controller = { suspended: true, resume: function(getValue){ var nextValue; if(getValue){ nextValue = getValue(); } if($pointer == 0){ // start of function $pointer++; // execute until the yield operator and return the value passed to yield return getAndFrob(url1); } if($pointer == 1){ // continuation from the yield $pointer++; return getAndMunge(url2); } if($pointer == 2){ // continuation from the yield $pointer++; // continue execution until the return operator $controller.suspended = false; // no more yield, function is done return getAndGrok(url3); } if($pointer > 2){ throw new Error("Can not resume a function that has returned"); } } }; // call the startCoroutine function return startCoroutine($controller); } function getAndFrob(url) { var $pointer = 0; // used to keep track of where we are // create the controller var $controller = { suspended: true, resume: function(getValue){ var nextValue; if(getValue){ nextValue = getValue(); } if($pointer == 0){ // start of function $pointer++; // execute until the yield operator and return the value passed to yield var xhr = new SimpleXHR(url); return xhr.get(); } if($pointer == 1){ // continuation from the yield $pointer++; var data = nextValue; return sleep(TIMEOUT); } if($pointer == 2){ // continuation from the yield $pointer++; // continue execution until the return operator $controller.suspended = false; // no more yield, function is done return frob(data); } if($pointer > 2){ throw new Error("Can not resume a function that has returned"); } } }; // call the startCoroutine function return startCoroutine($controller); } // Implementation of the continueWith proposal using the yield/startCoroutine proposal function simpleContinuationHandler(controller){ function handleResult(value){ if(!controller.suspended){ return value; } if(value && typeof value.continueWith === "function"){ var waiting = true; return value.continueWith(function(resume){ if(!waiting){ throw new Error("can't resume stack"); } waiting = false; return handleResult(resume()); }); } else{ return handleResult(controller.resume(function(){ return value; })); } } return handleResult(controller.resume()); } And the library functions defined above (Continuation, sleep, and SimpleXHR) would work with this startCoroutine implementation and translation. > >> Do you prefer basing single-frame continuations on new non-latin >> character syntax instead of using the "yield" keyword (hadn't >> realized it was already reserved in ES5 strict-mode when I did >> the first proposal)? > > I don't follow you. Non-latin? > > Dave > > I just meant "yield" vs "->()". - -- Kris Zyp SitePen (503) 806-1841 http://sitepen.com -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAku6LbEACgkQ9VpNnHc4zAzEBgCeM+TI39RYjLduBx4RTDaVcfMx UfMAn1SDT3GWdKtxl43xBQkX46nq1neC =Qwpo -----END PGP SIGNATURE----- _______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss