{
  "name": "cps",
  "description": "A continuation passing style library to help the coding of asynced programs in Javascript/Node.js.",
  "main": "./lib/cps",
  "author": {
    "name": "Chiyan Chen"
  },
  "version": "0.2.1",
  "repository": {
    "type": "git",
    "url": "https://github.com/redblaze/cps.git"
  },
  "bugs": {
    "url": "https://github.com/redblaze/cps/issues"
  },
  "licenses": [
    {
      "type": "MIT",
      "url": "https://github.com/redblaze/cps/raw/master/LICENSE"
    }
  ],
  "jam": {
    "main": "lib/cps.js",
    "include": [
      "lib/cps.js",
      "README.md",
      "LICENSE"
    ]
  },
  "readme": "\n# cps\n\nA CPS (Continuation Passing Style) library to ease the\nevent-driven/asynchronized coding style in node.js.  There seems to be\nenough node.js libs (e.g. async) doing the same thing, why yet\nanother?  This lib is notably different from other libs in\nexception handling.  Using cps:\n\n* Any \"throw\" statements in the procedures will be transformed to an\n  application of the callback onto the error object.\n* A \"rescue\" function is provided, which can be used to catch such\n  exceptions pass through the callbacks.\n\nThis consistently recovers the try/catch functionality in continuation\npassing style programming.\n\n\n\n## Install\n\n```text\nnpm install cps\n```\n\n## Terminologies\n\n### Callback\n\nWe call a function of the following form a callback:\n\n```javascript\nfunction(err, res) {\n  // process the err and res\n}\n```\n\nA callback is a function that takes two arguments, \"err\" and \"res\".\nSemantically, a non-null \"err\" corresponds to a program exception;\nwhile a null \"err\" corresponds to normal return without any\nexceptions.\n\n### Procedure\n\nWe call a function of the following form a procedure:\n\n```javascript\nfunction(arg1, arg2, ..., callback) {\n  // do some work with the arguments and then invoke the callback to continue\n}\n```\n\nA procedure is a function that takes a callback as the last argument.\nSemantically, a procedure does some work with the input arguments and\nat some point, call the callback to continue.  Note that a call to the\n\"callback\" argument MUST always be a tail call.  In particular, the\nfollowing is a procedure:\n\n```javascript\nfunction(callback) {\n  // do some work and then invoke the callback to continue\n}\n```\n\n\n## API Document\n\n* [seq](#seq)\n* [pwhile](#pwhile)\n* [peach](#peach)\n* [pmap](#pmap)\n* [pfor](#pfor)\n* [rescue](#rescue)\n* [parallel](#parallel)\n\n<a name=\"seq\"/>\n### seq(array_of_procedures, callback)\n\nSequence a list of procedures.  Note that the result of each procedure\nis fed into the next procedure in the listed order.\n\n__Example__\n\n```javascript\nvar concatFile = function(f1, f2, resFile, cb) {\n    var contentOfA, contentOfB;\n    \n    cps.seq([\n        function(_, cb) {\n            fs.readFile(f1, cb);\n        },\n        function(res, cb) {\n            contentOfA = res;\n            fs.readFile(f2, cb);\n        },\n        function(res, cb) {\n            contentOfB = res;\n            fs.writeFile(resFile, contentA + contentB, cb);\n        }\n    ], cb);\n};\n```\n\n<a name=\"pwhile\">\n### pwhile(bool_procedure, repeat_body_procedure, cb)\n\nAn asynchronized version of while loop.\n\n__Example__\n\nConsider a world in which arithmatic operations do not exists and must\nbe accomplished through alien technology.  Then the Fibonacci function\nneeds to be written in the following way:\n\n```javascript\nvar alienAdd = function(a, b, cb) {\n    setTimeout(function() {\n        cb(null, a + b);\n    }, 0);\n};\n\nvar asyncFib = function(n, cb) {\n    if (n < 0) {\n        throw new Error('fib input error');\n    }\n    if (n == 0) {return cb(null, 1);}\n    if (n == 1) {return cb(null, 1);}\n\n    var a = 1, \n    b = 1, \n    i = 2;\n    cps.seq([\n        function(_, cb) {\n            cps.pwhile(\n                function(cb) {\n                    cb(null, i <= n);\n                },\n                function(cb) {\n                    cps.seq([\n                        function(_, cb) {\n                            alienAdd(a, b, cb);\n                        },\n                        function(res, cb) {\n                            a = b;\n                            b = res;\n                            alienAdd(i, 1, cb);\n                        },\n                        function(res, cb) {\n                            i = res;\n                            cb();\n                        }\n                    ], cb);\n                },\n                cb\n            );\n        },\n        function(_, cb) {\n            cb(null, b);\n        }\n    ], cb);\n};\n```\n\n<a name=\"peach\"/>\n### peach(arr, procedure_for_each_element, callback)\n\nApply a procedure on an array sequentially.\n\n__Example__\n\nThen in the same \"arithmetic-less\" world, print out the first 10 Fibonacci numbers.\n\n```javascript\ncps.peach(\n    [1,2,3,4,5,6,7,8,9,10],\n    function(el, cb) {\n        cps.seq([\n            function(_, cb) {\n                asyncFib(el, cb);\n            },\n            function(res, cb) {\n                console.log(res);\n                cb();\n            }\n        ], cb);\n\n    },\n    cb\n);\n```\n\n<a name=\"pmap\" />\n### pmap(arr, procedure_for_each_element, callback)\n\nApply a procedure on an array sequentially, and record the results in another array, which is pass to the callback.\n\n__Example__\n\nYou can also map it out first and then log the result list.\n\n```javascript\ncps.seq([\n    function(_, cb) {\n        cps.pmap(\n            [1,2,3,4,5,6,7,8,9,10],\n            function(el, cb) {\n                asyncFib(el, cb);\n            },\n            cb\n        );\n    },\n    function(res, cb) {\n        console.log(res);\n        cb();\n    }\n], cb);\n```\n\n<a name=\"pfor\" />\n### pfor(number_of_iterations, procedure_for_each_index, callback)\n\nApply a procedure on a sequence of consecutive indices, starting of 0.\n\n__Example__\n\n\n```javascript\nvar sum = 0;\ncps.seq([\n    function(_, cb) {\n        console.log('here');\n        cps.pfor(10, function(i, cb) {\n            setTimeout(function() {\n                sum += i;\n                console.log(sum);\n                cb();\n            }, 1000);\n        }, cb);\n    },\n    function(_, cb) {\n        console.log(sum);\n        cb(null, 'ok');\n    }\n], cb);\n```\n\n<a name=\"rescue\"/>\n### rescue(try_clause_procedure, catch_clause_procedure, callback)\n\nAn asyned version of try/catch.  It take two procedures as arguments.  If the first one fails, the second is executed to rescue.\n\n__Example__\n\nWhat if there's some invalid input?  Let's catch it without disturbing the overall flow.\n\n```javascript\ncps.seq([\n    function(_, cb) {\n        cps.pmap(\n            [1,2,3,4,5,6,7,8,9,10, -1],\n            function(el, cb) {\n                cps.rescue({\n                    'try': function(cb) { // try clause\n                        asyncFib(el, cb);\n                    },\n                    'catch': function(err, cb) { // catch clause\n                        console.log(err);\n                        cb(null, -1);\n                    },\n                    'finally': function(cb) { // finally\n                        console.log(\"always print this whether it's good or bad.\");\n                        cb(); \n                    }\n                }, cb);\n            },\n            cb\n        );\n    },\n    function(res, cb) {\n        console.log(res);\n        cb();\n    }\n], cb);\n```\n\n<a name=\"parallel\"/>\n### parallel(array_of_procedures, callback)\n\nParallel a list of procedures.  The top level callback is only called\nafter each parallel procedure finishes, regardless the procedure\nsucceeds or fails.  The callback will never take a non-null error\nparameter; the result parameter is an array of the following form:\n\n```js\n[\n   {\"status\": \"ok\", \"data\": res},  /* in case the procedure in the \n                                      corresponding position succeeds \n                                      with result res\n                                   */\n   {\"status\": \"error\", \"error\": err}  /* in case the procedure in the \n                                         corresponding position fails \n                                         with error err\n                                      */\n   // ...\n]\n```\n\n\n__Example__\n\nSee \"thread b\" being printed out before \"thread a\":\n\n```javascript\nvar parallelTest = function(cb) {\n    cps.parallel([\n        function(cb) {\n            setTimeout(function() {\n                console.log('3');\n                cb(new Error('kaz'));\n            }, 3000);\n        },\n        function(cb) {\n            setTimeout(function() {\n                console.log('1');\n                cb(null, 'ok');\n            }, 2000);\n        },\n        function(cb) {\n            setTimeout(function() {\n                console.log('2');\n                cb(new Error('foobar'));\n            }, 1000);\n        }\n    ], cb);\n};\n```\n\nRunning this procedure will yield the following output:\n\n```text\n2\n1\n3\n[ { status: 'error', error: [Error: kaz] },\n  { status: 'ok', data: 'ok' },\n  { status: 'error', error: [Error: foobar] } ]\n```\n\n",
  "readmeFilename": "README.md",
  "homepage": "https://github.com/redblaze/cps",
  "_id": "cps@0.2.1",
  "dist": {
    "shasum": "9139bc3ee4736cba2d508c62cf5f1fcf2948711a"
  },
  "_from": "cps@*",
  "_resolved": "https://registry.npmjs.org/cps/-/cps-0.2.1.tgz"
}
