{"id":18260044,"url":"https://github.com/roppa/funcker","last_synced_at":"2025-04-08T23:44:38.923Z","repository":{"id":146092843,"uuid":"83544496","full_name":"roppa/funcker","owner":"roppa","description":"Functional programming learning exercise","archived":false,"fork":false,"pushed_at":"2018-05-17T11:27:02.000Z","size":164,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-14T18:36:27.612Z","etag":null,"topics":["curry","functional-programming","javascript","library","notation"],"latest_commit_sha":null,"homepage":null,"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/roppa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-01T10:54:03.000Z","updated_at":"2021-02-23T09:54:21.000Z","dependencies_parsed_at":null,"dependency_job_id":"9eda74b3-8e9d-49ef-ba88-982a64f44e31","html_url":"https://github.com/roppa/funcker","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/roppa%2Ffuncker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roppa%2Ffuncker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roppa%2Ffuncker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roppa%2Ffuncker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/roppa","download_url":"https://codeload.github.com/roppa/funcker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247947825,"owners_count":21023058,"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":["curry","functional-programming","javascript","library","notation"],"created_at":"2024-11-05T10:41:42.921Z","updated_at":"2025-04-08T23:44:38.903Z","avatar_url":"https://github.com/roppa.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![CircleCI](https://circleci.com/gh/roppa/funcker.svg?style=svg)](https://circleci.com/gh/roppa/funcker)\n\n# Funcker\n\nThis is my little foray into the world of functional programming. I mean, I was sold when Curry was mentioned. I called it funcker - 'func' in functional, plus getting your head around fp can be a bit of a 'funcker'.\n\nFunctional programming is one of the original paradigms of computing. Then things moved more towards a physical representation of the world - Object Oriented. Like the circle of life, we are moving back towards the past.\n\nFunctions are fast and make good use of disc space. Bruce Lee said be like water. Well, the body is 76% water, yet we are so solid. The idea then is to loosen up, to flow, to become pure and dynamic.\n\nIf you have done much TDD (please do!) you will know that as the tests get more specific, the code gets more generic. Same principle here - make the functions generic.\n\nBenefits of fp:\n\n - modularise code, making it more reusable\n - reduce the complexity of components\n - data flows along a pipeline\n - things less likely to break because there is no state or side effects\n\n## Nomenclature or Terminology  or Symbolic Representations of Concepts\n\n\u003cdl\u003e\n  \u003cdt\u003eFunction(al)\u003c/dt\u003e\n  \u003cdd\u003eAn expression related to an input or inputs. Of or relating to this\u003c/dd\u003e\n  \u003cdt\u003eMutable\u003c/dt\u003e\n  \u003cdd\u003eLiable to change, from latin 'to change'\u003c/dd\u003e\n  \u003cdt\u003eImmutable\u003c/dt\u003e\n  \u003cdd\u003eNot changing\u003c/dd\u003e\n  \u003cdt\u003ePure\u003c/dt\u003e\n  \u003cdd\u003eNot mixed, sound, free of contamination\u003c/dd\u003e\n  \u003cdt\u003eCurry\u003c/dt\u003e\n  \u003cdd\u003eConverting 1 function with n arguments into n functions each with 1 argument\u003c/dd\u003e\n  \u003cdt\u003eHigher order function\u003c/dt\u003e\n  \u003cdd\u003eA function that takes other functions as parameters\u003c/dd\u003e\n  \u003cdt\u003eReactive programming\u003c/dt\u003e\n  \u003cdd\u003eUsing the 'observable' pattern and treating things as streams and reacting to events in them\u003c/dd\u003e\n  \u003cdt\u003eDeclarative\u003c/dt\u003e\n  \u003cdd\u003eOpposite of imperative, not specifying the exact procedure, using expressions, more like 'map, then filter, then reduce'\u003c/dd\u003e\n  \u003cdt\u003eImperative\u003c/dt\u003e\n  \u003cdd\u003e'specially ordered', opposite of declarative, procedural, writing out everything specifically 'for loop over array, put result in another array, loop again and copy certain values, then loop again and calculate total'\u003c/dd\u003e\n  \u003cdt\u003eSide effect\u003c/dt\u003e\n  \u003cdd\u003eChanging something outside of itself\u003c/dd\u003e\n  \u003cdt\u003eDecomposition\u003c/dt\u003e\n  \u003cdd\u003eDecay, but more like breaking into component parts\u003c/dd\u003e\n  \u003cdt\u003eReferential transparency\u003c/dt\u003e\n  \u003cdd\u003eGiven parameters should always return the same values. transparency because it is clear you get the same results, referential because of the parameters used\u003c/dd\u003e\n  \u003cdt\u003eExpression\u003c/dt\u003e\n  \u003cdd\u003eAnything that results in a value\u003c/dd\u003e\n  \u003cdt\u003eState\u003c/dt\u003e\n  \u003cdd\u003eThe condition something is in at a particular time\u003c/dd\u003e\n  \u003cdt\u003eStateless\u003c/dt\u003e\n  \u003cdd\u003eNot in a particular condition that persists\u003c/dd\u003e\n  \u003cdt\u003eArity\u003c/dt\u003e\n  \u003cdd\u003eThe number of arguments passed to a function. myFunc(1, 2, 3) has an arity of 3\u003c/dd\u003e\n  \u003cdt\u003eList comprehension\u003c/dt\u003e\n  \u003cdd\u003eEncapsulates the functionality of map and filter into for...of syntax\u003c/dd\u003e\n  \u003cdt\u003eChain(ing)\u003c/dt\u003e\n  \u003cdd\u003eBeing able to chain functions like a().b().c()\u003c/dd\u003e\n  \u003cdt\u003e:: (Has type)\u003c/dt\u003e\n  \u003cdd\u003eStandard notation for fp: \u003ccode\u003efunction_name :: input_type -\u003e value\u003c/code\u003e\u003c/dd\u003e\n\u003c/dl\u003e\n\n## Notation\n\nThere is a standard notation for functional programming worth covering first:\n\n```\nf :: input -\u003e output\n```\n\nThe 'f' is a function, the parameters for that function come after the '::' (or sometimes a single ':'). The '::' means 'has type'. The return value of the function comes after the comma, and the '-\u003e' is a function with its returning value. So this notation:\n\n```\nf :: number -\u003e number\n```\n\nBecomes:\n\n```javascript\nconst add10 = (x) =\u003e x + 10;\n```\n\n## Higher order functions\n\nFunctions are essentially objects, first class citizens, and can move around as such. Hence we have 'higher order' functions - functions that take other functions as parameters and/or return functions.\n\n## Arity\n\nIt is best practice that the number of parameters a function takes needs to be a maximum of two. A function really should do one thing and one thing only. Imagine how many branches there would be if a function got 3, 4, 5 or more parameters? That could indicate a complex function - not good.\n\nFunctions should do one thing and one thing only. They should not modify anything other than in its own scope.\n\n## Closure\n\nThe definition of a closure is 'a function object that has a reference to the variables in the context it was created in'.\n\n## Mutability\n\nFunctions should be pure. This could lead to problems when parameters are references to an object. If that object is changed within a function then a side effect results. Not good.\n\n## Monads\n\nA monad is an object.\n\n## Functions in the 'funker' example\n\n### .curry\n\nIf you have ever used bind, then you are half way there. Currying is the same as bind, but applied in a different way. With bind a new function is returned with the 'this' parameter of the original function set to the first parameter of the bind function. This is partial application, and that is what currying is - partial application.\n\nCurrying takes 1 function with n arguments, and converts it to n functions with 1 argument. We can then create a function that already has most of the data it needs held in a closure, and then we can reuse it.\n\nSo instead of:\n\n```javascript\nadd(1, 2, 3, 4, 5, 6);\n```\n\nit becomes:\n\n```javascript\nadd(1)(2)(3)(4)(5)(6)\n```\n\nThat looks a bit weird and not very useful. So to convert a function that usually takes multiple params:\n\n```javascript\nlet addToFifteen = funcker.curry(add, 1, 2, 3, 4, 5);\nlet addToThirty = funcker.curry(add, 10, 10, 10);\nconsole.log(addToFifteen(15));  //30\nconsole.log(addToThirty(15));  //45\n```\n\n### .filter\n\nCurried Array.filter\n### .get\n\nSo with imperative coding, to get an attribute for each object in an array we would have to write a for loop, then access the property. Then when we need to do it somewhere else we would write another for loop ...\n\nNot with higher order functions. We simply want to 'get' a property. So we can pass this to a map or forEach like so:\n\n```javascript\n[{ name: 'Billy', age: 42 }, { name: 'Bob', age: 24 }].map(funker.get('name'));\n```\n\n### .only\n\nGet a new object with only the fields specified in a space delimited string.\n\n```javascript\nconst getNameAge = only('name age');\nconst userObject = { name: 'Tad', age: 40, secret: 'shhh, don\\'t tell anyone' };\nconsole.log(getNameAge(userObject)); // { name: 'Tad', age: 40 }\n```\n\n### .compose\n\nFunction composition: s: f1 =\u003e f2 =\u003e f3 =\u003e f1(f2(f3(s)))\n\nTakes an array of functions and applies them in reverse order to the supplied value.\n\n```javascript\ncompose([f1, f2, f3], value) =\u003e f1(f2(f3(value)))\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froppa%2Ffuncker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froppa%2Ffuncker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froppa%2Ffuncker/lists"}