| // jonas :: https://github.com/michaelsbradleyjr/jonas | |
| // :: https://npmjs.org/package/jonas | |
| var jonas = require("jonas"), | |
| Cont = jonas.Monad.Cont, | |
| pCont = jonas.Monad.pCont, | |
| Q = jonas.Q, | |
| util = require("util"); | |
| // see: http://en.wikipedia.org/wiki/Call-with-current-continuation | |
| // for reference, here is the "yin-yang" call/cc puzzle as it's commonly | |
| // implemented in Scheme: | |
| // (let* ((yin | |
| // ((lambda (cc) (display #\@) cc) (call-with-current-continuation (lambda (c) c)))) | |
| // (yang | |
| // ((lambda (cc) (display #\*) cc) (call-with-current-continuation (lambda (c) c))))) | |
| // (yin yang)) | |
| // we'll implement it twice in JavaScript, per jonas; the first implementation | |
| // will be syncrhronous and the second one asynchronous | |
| /* -------------------------------------------------------------------------- */ | |
| // Synchronous implementation - Cont monad | |
| function λ(c) { return c(c); } | |
| var mReturn = Cont.mReturn, | |
| mFn = function (t) { | |
| return function (cc) { | |
| util.print(t); | |
| return mReturn(cc); | |
| }; | |
| }; | |
| Cont.callCC( λ ).mBind( mFn("@") )( Cont.callCC( λ ).mBind( mFn("*") ) ); | |
| // => @*@**@***@****@*****@******@*******@********@*********@**********@*****... | |
| // will blow the call stack rather quickly; jonas is currently being revised so | |
| // that synchronous monadic `run` does not involve recursion, i.e. it won't blow | |
| // the stack, stay tuned... | |
| // comment out the last line above in order to run the second implementation | |
| // below | |
| /* -------------------------------------------------------------------------- */ | |
| // Asynchronous implementation - pCont monad | |
| mReturn = pCont.mReturn; | |
| mFn = function (t, delay) { | |
| return function (cc) { | |
| util.print(t); | |
| // since we're using pCont, we can introduce a variable delay | |
| // in terms of a promise; resolution of the promises is | |
| // handled automatically by the "monadic plumbing" of pCont; | |
| // if delay is null or the value "s", the computation will | |
| // implicitly make use of the JavaScript environment's | |
| // setImmediate function per Q's contract re: `then`, owing to | |
| // pCont's "inner monad" (pIdentity) | |
| return mReturn( | |
| ( delay == null ) || | |
| ( delay === "s" ) ? cc | |
| : Q.delay(delay).then( | |
| function () { return cc; } | |
| ) | |
| ); | |
| }; | |
| }; | |
| pCont.callCC( λ ).mBind( mFn("@", 100) )( pCont.callCC( λ ).mBind( mFn("*", 100) ) ); | |
| // same output as above, but ~100ms delay between each character printed; won't | |
| // blow the stack since each step in the monadic computation involves a trip | |
| // across the event loop, but memory consumption is unbounded and the process | |
| // will eventually crash |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment
Hide comment
CrypticSwarm
commented
May 28, 2013
|
Might want to add a note that you are implementing this twice. Once for the regular continuation monad and once for your promise continuation monad. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Might want to add a note that you are implementing this twice. Once for the regular continuation monad and once for your promise continuation monad.