{"id":19987629,"url":"https://github.com/raederdev/co-functional","last_synced_at":"2025-07-09T14:04:57.895Z","repository":{"id":57201810,"uuid":"49544795","full_name":"RaederDev/co-functional","owner":"RaederDev","description":"co-functional is a MIT licenced library that provides several functions for use with the co library.","archived":false,"fork":false,"pushed_at":"2016-01-25T20:45:00.000Z","size":39,"stargazers_count":10,"open_issues_count":2,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-03T18:52:26.398Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RaederDev.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.MD","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-01-13T02:50:30.000Z","updated_at":"2024-11-14T03:11:21.000Z","dependencies_parsed_at":"2022-09-17T11:22:49.147Z","dependency_job_id":null,"html_url":"https://github.com/RaederDev/co-functional","commit_stats":null,"previous_names":["n0ps32/co-functional"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/RaederDev/co-functional","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RaederDev%2Fco-functional","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RaederDev%2Fco-functional/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RaederDev%2Fco-functional/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RaederDev%2Fco-functional/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RaederDev","download_url":"https://codeload.github.com/RaederDev/co-functional/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RaederDev%2Fco-functional/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264473862,"owners_count":23613957,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T04:37:30.830Z","updated_at":"2025-07-09T14:04:57.873Z","avatar_url":"https://github.com/RaederDev.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# co-functional\n\nco-functional is a MIT licenced library that provides several functions for use with the [co](https://github.com/tj/co)\nlibrary. Functions are curried (where possible) and are always iteratee-first, data last.\n\nCurrently the library provides the following functions:\n- [bind, lazyBind](#user-content-bind)\n- [compose](#user-content-compose)\n- [filter, filterSerial](#user-content-filter)\n- [forEach, forEachSerial](#user-content-for)\n- [map, mapSerial](#user-content-map)\n- [reduce](#user-content-reduce)\n\n## Installation\nYou can install co-functional using npm:\n```\nnpm install --save co-functional\n```\nThen you can require it in your code:\n```\nconst cf = require('co-functional');\n```\n\nBabelify transforms are defined in package.json.  \nSo you can also require co-functional in a browser in a non-ES2015 environment using browserify with babelify.\n\n## Functions\n\nNote that while in the following examples the returned Promises is handeled manually\nyou can of course yield the output of each function if you have a GeneratorFunction that is wrapped with co.\n\n###[\u003ca name=\"bind\"\u003e\u003c/a\u003ebind, lazyBind](#bind)\n\n**\"bind\"** binds the given function to the given context and executes it.  \nIf the given function is a GeneratorFunction it will be wrapped with co.  \n\"bind\" is curried so you may leave of the second parameter to delay execution.  \n```javascript\nconst promise = cf.bind(function* (argument) {\n    console.log(this); //scope that was bound\n    console.log(argument); //1234\n}, this, 1234).then(...);\n```\n\n**\"lazyBind\"** binds the given function to the given context and returns the bound function.  \nIf the given function is a GeneratorFunction it will be wrapped with co.  \n\"lazyBind\" is curried so you may leave of the second parameter to delay execution.  \n```javascript\nconst bound = cf.lazyBind(function* (argument) {\n    console.log(this); //scope that was bound\n    console.log(argument); //1234\n}, this);\n\nconst promise = bound(1234);\npromise.then(...);\n```\n\n###[\u003ca name=\"compose\"\u003e\u003c/a\u003ecompose](#compose)\n\n**\"compose\"** composes the given functions right to left.  \nIf a function returns a promise the chain will wait for the promise to resolve and continue with the resolved value.  \nIf you pass a generator function as a function it will be wrapped with co and executed.  \nYou may pass multiple parameters to the first function but note that the following functions will only receive one value.\n```javascript\nconst composed = cf.compose(\n     function(n) {\n         console.log(n); //will log 3 to the console\n     },\n     function(n) {\n         return Promise.resolve(n + 1);\n     },\n     function* (n) {\n         return yield Promise.resolve(n + 1)\n     },\n     function(n) {\n         return n + 1;\n     }\n);\n\ncomposed(0).then(...).catch(...);\n```\n\n###[\u003ca name=\"filter\"\u003e\u003c/a\u003efilter, filterSerial](#filter)\n\n**\"filter\"** filters the given Array using the given generator function asynchronously.  \nThis function is curried so you may leave of the second parameter to delay execution.  \nIf the function returns a Promise the Promise will be resolved and the result will be used.  \nIf the given function is a GeneratorFunction it will be wrapped with co.  \n\n```javascript\nconst asyncIsOddNumber = number =\u003e Promise.resolve(number % 2 === 0);\nconst promise = cf.filter(function* (number) {\n    return yield asyncIsOddNumber(number);\n}, [1, 2, 4]);\n\npromise.then(oddNumbers =\u003e {\n    console.log('All odd numbers: ', oddNumbers);\n});\n```\n\n**\"filterSerial\"** filters the given Array using the given generator function asynchronously but one after another.  \nIf you want the highest possible speed you should not use this function but the completely asynchronous filter function!  \nThat means your elements will get filtered in order and the function will wait until something\nhas been returned by your GeneratorFunction before continuing execution.\n\nThis function is curried so you may leave of the second parameter to delay execution.  \nIf the function returns a Promise the Promise will be resolved and the result will be used.  \nIf the given function is a GeneratorFunction it will be wrapped with co.  \n\n```javascript\nconst asyncIsOddNumber = number =\u003e Promise.resolve(number % 2 === 0);\nconst promise = cf.filterSerial(function* (number) {\n    return yield asyncIsOddNumber(number);\n}, [1, 2, 4]);\n\npromise.then(oddNumbers =\u003e {\n    console.log('All odd numbers: ', oddNumbers);\n});\n```\n###[\u003ca name=\"for\"\u003e\u003c/a\u003eforEach, forEachSerial](#for)\n\n**\"forEach\"** loops over the given Array or Object asynchronously.  \nThis function is curried so you may leave of the second parameter to delay execution.  \nThe value is passed as the first, the key/index as the second parameter.  \nIf the function returns a Promise the Promise execution will halt until all Promises have been resolved.  \nIf the given function is a GeneratorFunction it will be wrapped with co.  \n\n```javascript\nconst promise = cf.forEach(function* (data, index) {\n   console.log(data, index);\n}, [2, 4]);\n\nconst promise2 = cf.forEach(function* (data, key) {\n   console.log(data, key);\n}, { a: 2, b: 4});\n```\n\n**\"forEachSerial\"** loops over the given Array or Object asynchronously but one after another.  \nIf you want the highest possible speed you should not use this function but the completely asynchronous forEach function!  \nThat means your elements will get looped over in order and the function will wait until something  \nhas been returned by your function before continuing execution.\n\nThis function is curried so you may leave of the second parameter to delay execution.  \nThe value is passed as the first, the key/index as the second parameter.  \nIf the given function is a GeneratorFunction it will be wrapped with co.  \n\n```javascript\nconst promise = cf.forEachSerial(function* (data, index) {\n   console.log(data, index);\n}, [2, 4]);\n\nconst promise2 = cf.forEachSerial(function* (data, key) {\n   console.log(data, key);\n}, { a: 2, b: 4});\n```\n\n###[\u003ca name=\"map\"\u003e\u003c/a\u003emap, mapSerial](#map)\n**\"map\"** maps over the given Array or Object asynchronously.  \nIf you pass an object it will be cloned to avoid modification.  \nThis function is curried so you may leave of the second parameter to delay execution.  \nThe value is passed as the first, the key/index as the second parameter.  \nIf the function returns a Promise the Promise will be resolved and the result will be used.  \nIf the given function is a GeneratorFunction it will be wrapped with co.  \n\n```javascript\nconst double = value =\u003e Promise.resolve(value * 2);\n\nconst promise = cf.map(function* (number, index) {\n   const someAsyncValue = yield double(number);\n   return someAsyncValue;\n}, [2, 4]);\n\nconst promise2 = cf.map(function* (data, key) {\n   const someAsyncValue = yield double(data);\n   return someAsyncValue;\n}, { a: 2, b: 4});\n```\n\n**\"mapSerial\"** maps over the given Array or Object asynchronously but one after another.  \nIf you pass an object it will be cloned to avoid modification.  \nIf you want the highest possible speed you should not use this function but the completely asynchronous map function!  \nThat means your elements will get mapped over in order and the function will wait until something\nhas been returned by your function before continuing execution.  \n\nThis function is curried so you may leave of the second parameter to delay execution.  \nThe value is passed as the first, the key/index as the second parameter.  \nIf the function returns a Promise the Promise will be resolved and the result will be used.  \nIf the given function is a GeneratorFunction it will be wrapped with co.  \n\n```javascript\nconst double = value =\u003e Promise.resolve(value * 2);\n\nconst promise = cf.mapSerial(function* (number, index) {\n   const someAsyncValue = yield double(number);\n   return someAsyncValue;\n}, [2, 4]);\n\nconst promise2 = cf.mapSerial(function* (data, key) {\n   const someAsyncValue = yield double(data);\n   return someAsyncValue;\n}, { a: 2, b: 4});\n```\n\n###[\u003ca name=\"reduce\"\u003e\u003c/a\u003ereduce](#reduce)\n**\"reduce\"** reduces the given Array using the given generator function asynchronously but one after another.  \nThat means your elements will get reduced in order and the function will wait until something\nhas been returned by your function before continuing execution.\n\nThe function is passed the accumulator as the first Parameter, the current value as the second value\nand the current Array index as the third parameter.\n\nThis function is curried so you may leave of any parameter to delay execution.  \nIf the function returns a Promise the Promise will be resolved and the result will be used.  \nIf the given function is a GeneratorFunction it will be wrapped with co.  \n\n```javascript\nconst asyncAddNumber = (a, b) =\u003e Promise.resolve(a + b);\nconst promise = cf.reduce(function* (accumulator, number, arrayIndex) {\n    return yield asyncAddNumber(number, accumulator);\n}, 10, [1, 2]);\n\npromise.then(result =\u003e console.log(result)); //13\n```\n\n## Tests\nTo execute the tests run\n```\nnpm test\n```\nin the main directory.\nIf you contribute new code make sure to include tests for your code!","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraederdev%2Fco-functional","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fraederdev%2Fco-functional","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraederdev%2Fco-functional/lists"}