{"id":22505375,"url":"https://github.com/azer/functools","last_synced_at":"2025-08-03T11:33:16.568Z","repository":{"id":66734282,"uuid":"1213089","full_name":"azer/functools","owner":"azer","description":"DEPRECATED: Use small modules instead","archived":false,"fork":false,"pushed_at":"2013-02-20T06:44:10.000Z","size":171,"stargazers_count":79,"open_issues_count":0,"forks_count":5,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-04-15T03:09:34.362Z","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":"wtfpl","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/azer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2011-01-01T22:31:58.000Z","updated_at":"2023-03-21T10:06:45.000Z","dependencies_parsed_at":"2023-02-20T10:30:22.659Z","dependency_job_id":null,"html_url":"https://github.com/azer/functools","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azer%2Ffunctools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azer%2Ffunctools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azer%2Ffunctools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azer%2Ffunctools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/azer","download_url":"https://codeload.github.com/azer/functools/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228540869,"owners_count":17934034,"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-12-07T00:17:58.158Z","updated_at":"2024-12-07T00:17:58.856Z","avatar_url":"https://github.com/azer.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"functools is a JavaScript library for functional programming.\n\nInspired by: Common Lisp, Clojure and Python.\nTested on: Chrome, IE6 and Node. (See *test/results.json* for details)\n\n# SYNOPSIS\n\nFunction Composition:\n\n```javascript\nvar compose = require(\"functools\").compose;\n\ncompose(select, update, prettify, display)(\"body .messages\");\n```\n\n\u003ca name=\"async-function-composition\"\u003e\u003c/a\u003e\nAsync Function Compositon:\n\n```javascript\n\nfunction findFiles(path, callback){  ... }\nfunction readContents(files, callback){ ... }\nfunction upload(files, callback){}\n\ncompose.async(findFiles, readContents, upload)('~/messages', function(error, uploadResult){\n  ...\n});\n```\n\nAsync Juxtaposition:\n\n```javascript\nfunction turkish(word, callback){ /* some magic here */ }\nfunction french(word, callback){ /* some magic here */ }\nfunction polish(word, callback){ /* some magic here */ }\n\njuxt.async({ 'tr': turkish, 'fr': french, 'pl': polish })(\"hello\", function(error,  results){\n  assert.equal(results.tr, \"merhaba\");\n  assert.equal(results.fr, \"bonjour\");\n  assert.equal(results.pl, \"cześć\");\n});\n```\n\nCurrying:\n\n```javascript\nvar fn = require(\"functools\");\n\nvar pickEvens = fn.curry(fn.filter)(function(num){ return num%2==0 });\n\npickEvens([3,1,4]) // returns [4]\npickEvens([1,5,9,2,6,5]) // returns [2,6]\n```\n\n\n# INSTALL\n\n```bash\n$ npm install functools\n```\n\nor\n\n```bash\n$ wget https://raw.github.com/azer/functools/master/lib/functools.js\n```\n\n# WHAT'S NEW?\n\n06.09.2012\n* each.async\n* memoize\n* memoize.async\n\n06.08.2012\n* IE6, IE7 and IE8 bugfixes\n* better testing\n\n# DOCUMENTATION\n\n* [compose](#compose)\n* [compose.async](#compose.async)\n* [curry](#curry)\n* [each](#each)\n* [each.async](#each.async)\n* [filter](#filter)\n* [filter.async](#filter.async)\n* [juxt](#juxt)\n* [juxt.async](#juxt.async)\n* [map](#map)\n* [map.async](#map.async)\n* [memoize](#memoize)\n* [memoize.async](#memoize.async)\n* [partial](#partial)\n* [reduce](#reduce)\n* [reduce.async](#reduce.async)\n\n\u003ca name=\"compose\" /\u003e\n## compose(*functions ...*)(*value*)\n\nCombine *functions* in a new one, passing the result of each function to next\none, from left to right.\n\n```javascript\nfunction cube(x){ return x*x*x };\n\ncompose(Math.sqrt,cube)(4); // returns 8\n```\n\n\u003ca name=\"compose.async\" /\u003e\n## compose.async(*functions ...*)(*value*,*callback*)\n\nAsynchronous function composition.\n\n```javascript\nvar messageTransmission = compose.async(receiveMessage, getUserProfiles, transmitMessage);\n\nmessageTransmission({ msg: \"Hello!\", 'from': 3, 'to': 1 }, function(error, result){\n  //\n})\n\nfunction receiveMessage(msg, callback){}\nfunction getUserProfiles(msg, callback){ ... callback(null, from, to, msg); }\nfunction transmitMessage(from, to, message, callback){}\n```\n\u003ca name=\"curry\" /\u003e\n## curry(*function*, *args ...*)\n\nTransform multiple-argument *function* into a chain of functions that return each other until all arguments are gathered.\n\n```javascript\nfunction sum(x,y){ return x+y; }\n\nvar add3 = curry(sum, 3);\n\nadd3(14); // returns 17\nadd3(20); // returns 23\n```\n\n\u003ca name=\"each\" /\u003e\n## each(*function*,*iterable*)\n\nCall *function* once for each element in *iterable*.\n\n```javascript\neach(function(el,ind,list){ console.assert( el == list[ind] ); }, [3, 1, 4]);\n```\n\n\u003ca name=\"each.async\" /\u003e\n## each.async(*function*,*iterable*,*callback*)\n\nCall async *function* once for each element in *iterable*, and *callback* after iteration.\n\n```javascript\n\n\u003e function uploadFile(filename, callback){\n  console.log('Uploading ', filename);\n  callback();\n}\n\n\u003e each.async(uploadFile, [ '/docs/intro', '/docs/body', '/docs/outro' ], function(error){\n\n  if(error){\n    console.log('Failed to upload files');\n    throw error;\n  }\n\n  console.log('All files has been uploaded successfully');\n\n});\n\n\u003e Uploading /docs/intro\nUploading /docs/body\nUploading /docs/outro\nAll files has been uploaded successfully\n```\n\n\u003ca name=\"filter\" /\u003e\n## filter(*function*,*iterable*)\n\nConstruct a new array from those elements of *iterable* for which *function* returns true.\n\n```javascript\nfilter(function(el,ind,list){ return el%2==0 }, [3, 1, 4]); // returns [4]\n```\n\n\u003ca name=\"filter.async\" /\u003e\n## filter.async(*function*,*iterable*, *callback*)\n\nCall async *function* once for each element in *iterable*, receiving a boolean\nparameter, and construct a new array of all the values for which *function*\nproduces *true*\n\n```javascript\n\nvar users = [ 3, 5, 8, 13, 21 ]; // only user#3 and user#8 have permission in this example\n\nfunction hasPermission(userId, callback){ ... callback(/* true or false */); }\n\nfilter.async(hasPermission, [3, 1, 4], function(permittedUsers){\n  assert.equal(permittedUsers.length, /* ? */);\n});\n\n```\n\n\u003ca name=\"juxt\" /\u003e\n## juxt(*functions ...*)\n\nTake a set of functions, return a function that is the juxtaposition of those\nfunctions. The returned function takes a variable number of arguments and\nreturns a list containing the result of applying each fn to the arguments.\n\n```javascript\nfunction inc1(n){ return n+1 };\nfunction inc2(n){ return n+2 };\nfunction inc3(n){ return n+3 };\n\njuxt(inc1, inc2, inc3)(314); // returns [315,316,317]\n```\n\n\u003ca name=\"juxt.async\" /\u003e\n## juxt.async(*functions ...*)\n\nAsync implementation of *juxt*.\n\n```javascript\nfunction turkish(word, callback){ /* some magic here */ }\nfunction french(word, callback){ /* some magic here */ }\nfunction polish(word, callback){ /* some magic here */ }\n\njuxt.async(turkish, french, polish)(\"hello\", function(error,  results){\n  assert.equal(results[0], \"merhaba\");\n  assert.equal(results[1], \"bonjour\");\n  assert.equal(results[2], \"cześć\");\n});\n```\n\n\u003ca name=\"map\" /\u003e\n## map(*function*,*iterable*)\n\nInvoke *function* once for each element of *iterable*. Creates a new iterable\ncontaining the values returned by the function.\n\n```javascript\n\nfunction square(n){\n  return n*n;\n}\n\nmap(square, [3,1,4,1,5,9]); // returns [9,1,16,1,25,81]\n```\n\nObjects can be passed as well;\n\n```javascript\nvar dict = { 'en':'hello', 'tr': 'merhaba', 'fr':'bonjour' };\n\nfunction capitalize(str){\n  return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\nmap(capitalize, dict); // returns { 'en':'Hello', 'tr':'Merhaba', 'fr':'Bonjour' }\n```\n\n\u003ca name=\"map.async\" /\u003e\n## map.async(*function*,*iterable*, *callback*)\n\nApply async *function* to every item of *iterable*, receiving a callback\nfunction which takes error (if there is) and replacement parameters.\n\n```javascript\nfunction readFile(id, callback){ ... callback(undefined, data); }\n\nmap.async(readFile, ['./foo/bar', './foo/qux', './corge'], function(error, files){\n  if(error) throw error;\n\n  console.log(files[0]); // will put the content of ./foo/bar\n});\n```\n\n\u003ca name=\"memoize\" /\u003e\n## memoize(*function*,*hasher*)\n\nReturn a memoized version of *function*. *hasher* is optional.\n\n```javascript\n\u003e function myfunc(n){\n    console.log(\"doing some work\");\n    return n + 10;\n}\n\n\u003e var myfuncMemo = memoize(myfunc);\n\u003e myfuncMemo(1);\n\"doing some work\"\n11\n\u003e myfuncMemo(1);\n11\n\u003e myfuncMemo(20);\n\"doing some work\"\n30\n\u003e myfuncMemo(20);\n30\n```\n\n\u003ca name=\"memoize.async\" /\u003e\n## memoize.async(*function*, *hasher*)\n\nMemoize given async *function* if it doesn't produce any error.\n\n```javascript\n\u003e function readFile(){ console.log('doing some work'); ... callback(undefined, buffer); }\n\n\u003e var readFileMemo = memoize.async(readFile);\n\n\u003e readFileMemo('/docs/readme', function(error, content){\n    console.log(content);\n});\n\"doing some work\"\n\n\u003e \"This is the Readme file\"\n\n\u003e readFileMemo('/docs/readme', function(error, content){\n    console.log(content);\n});\n\"This is the Readme file\"\n```\n\n\u003ca name=\"partial\" /\u003e\n## partial(*function*,*initial arguments*,*context *)\n\nReturn a new function which will call *function* with the gathered arguments.\n\n```javascript\nfunction testPartial(){\n  var args = reduce(function(x,y){ return x+\", \"+y },arguments);\n\n  console.log(\"this:\",this);\n  console.log(\"args:\",args);\n}\n\npartial(testPartial, [3,14], 3.14159)(1,5,9);\n```\n\nThe example code above will output:\n```\nthis: 3.14159\nargs: 3,14,1,5,9\n```\n\n\u003ca name=\"reduce\" /\u003e\n## reduce(*function*,*iterable*)\n\nApply *function* cumulatively to the items of *iterable*,  as to reduce the\n*iterable* to a single value\n\n```javascript\nreduce(function(x,y){ return x*y }, [3,1,4]); // returns 12\n```\n\n\u003ca name=\"reduce.async\" /\u003e\n## reduce.async(*function*,*iterable*, *callback*)\n\nAsync implementation of *reduce*.\n\n```javascript\n\nvar users = [2, 3, 5, 8, 13];\n\nfunction usernames(accum, userId){ ... callback(undefined, accum + ', ' + username); }\n\nreduce.async(usernames, users, function(error, result){\n  if(error) throw error;\n\n  console.log(result); // foo, bar, qux ...\n});\n\n```\n\n# Testing\n\n## On NodeJS:\n\n```\n$ npm test\n```\n\n## On Browsers\n\nRun `make test` command to publish the tests on `localhost:1314`. Visit the URL using the browser on which you want to run the tests. Stop the server (Ctrl+C) when you're done with testing.\n\nTo see the summary of results;\n\n```\n$ make test do=verify\nNot Tested: firefox, ie8, ie7\nPassed: ie6, webkit\n\nRevision: 1.3.0\nResults Source: test/results.json\nConfig: test/config.json\n```\n\n# SEE ALSO\n- [Functional Programming - Eloquent JavaScript](http://eloquentjavascript.net/chapter6.html)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fazer%2Ffunctools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fazer%2Ffunctools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fazer%2Ffunctools/lists"}