{"id":21076316,"url":"https://github.com/coderoad/coderoad-functional-school-deprecated","last_synced_at":"2025-07-13T05:35:57.278Z","repository":{"id":57202491,"uuid":"51133327","full_name":"coderoad/coderoad-functional-school-deprecated","owner":"coderoad","description":"Functional Programming in Javascript Tutorial","archived":false,"fork":false,"pushed_at":"2016-08-26T05:55:34.000Z","size":276,"stargazers_count":37,"open_issues_count":0,"forks_count":4,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-11-01T02:15:38.996Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://coderoad.github.io","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coderoad.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-02-05T07:47:48.000Z","updated_at":"2024-06-05T13:20:20.000Z","dependencies_parsed_at":"2022-09-15T13:20:32.846Z","dependency_job_id":null,"html_url":"https://github.com/coderoad/coderoad-functional-school-deprecated","commit_stats":null,"previous_names":["coderoad/coderoad-functional-school"],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderoad%2Fcoderoad-functional-school-deprecated","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderoad%2Fcoderoad-functional-school-deprecated/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderoad%2Fcoderoad-functional-school-deprecated/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderoad%2Fcoderoad-functional-school-deprecated/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coderoad","download_url":"https://codeload.github.com/coderoad/coderoad-functional-school-deprecated/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225413205,"owners_count":17470534,"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-19T19:27:50.263Z","updated_at":"2024-11-19T19:27:50.915Z","avatar_url":"https://github.com/coderoad.png","language":"JavaScript","readme":"# Functional School\n\nA trip through functional programming in Javascript using common built-in Javascript array methods such as `map` \u0026 `reduce`.\n\nBy the end, you should have an understanding of how to use array methods to manipulate semi-complex data.\n\nLevel: Intermediate\nKeywords: javascript, functional\nLength: 1-2 hours\n\n\n## CodeRoad\n\nCodeRoad is an open-sourced interactive tutorial platform for the Atom Editor. Learn more at [CodeRoad.io](http://coderoad.io).\n\n\n## Setup\n\n* install the tutorial package\n\n    `npm install --save coderoad-functional-school`\n\n* install and run the [atom-coderoad](https://github.com/coderoad/atom-coderoad) plugin\n\n\n## Outline\n\n##### Start\n\nUnderstanding the Data Set\n\nOver this tutorial series, we'll be changing and working with two different data sets. It'll be a big help to first understand what the data looks like.\n\n```json\nvar students = [\n  {\n    \"title\": \"Relational Databases\",\n    \"instructor\": \"Sean Quentin Lewis\",\n    \"name\": \"Ada Lovelace\",\n    \"score\": 91,\n    \"grade\": \"A\"\n  },\n  ...\n]\n```\n\nHere we have an array of \"student\" objects. To get the first item in the array, you can use the array index. Array indexes start at 0.\n\n```js\nconsole.log(\n  'first instructor', students[0].instructor\n);\n// first instructor Sean Quentin Lewis\n```\n\n##### Filter\n\nArray -\u003e Array of items that match a condition\n\nYou've hacked into the school's computer system, and just in time. The grades are in, but you're not too proud of your performance. That's okay, you have a plan: you're going to create a fake report card.\n\nIt would be great if you could `filter` the scores that your parents will see.\n\n`filter` takes a matching condition function and only returns items that result in true. As an example, look at `isA` below:\n\n```js\nfunction isA(x) {\n  return x === 'a';\n}\n```\n\n\nLike all of the methods in this chapter, `filter` is already part of the `Array.prototype`, so you can run it following any array. Each item in the array is passed into the params of the condition function, one by one. [Learn more](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter).\n\n```js\nconst list = ['a', 'b'];\nlist.filter(isA);\n\n// if isA(list[0]), add to output array\n// if isA(list[1]), add to output array\n//\n//\u003e ['a']\n```\n\nIf your data was composed of objects, we could use dot notation to find matches. Checkout `isB` below.\n\n```js\nfunction isB(x) {\n  return x.item === 'b'\n}\n\nconst list = [{item: 'a'}, {item: 'b'}];\nlist.filter(isB);\n//\u003e [{item: 'b'}]\n```\n\nWhere were we? Back to filtering our grades.\n\nThere's too much student data in the computer system. We'll have to sort through it. Have a look at an example below:\n\n```js\nconsole.log(students[0]);\n//\u003e { course: 'Web Security',\n//    instructor: 'Sue Denim',\n//    name: 'Rebecca Heineman',\n//    score: 93,\n//    grade: 'A' }\n```\n\n##### Sort\n\nArray -\u003e sorted Array\n\nYour grades are filtered down to your name and good scores - but wouldn't it be better if your best grades were displayed first, at the top? Besides, your parents rarely read anything through.\n\nYou can use the array method `sort` to arrange your data. Let's see how it works.\n\n```js\n['c', 'b', 'a'].sort();\n//\u003e ['a', 'b', 'c']\n\n[3, 2, 1].sort();\n//\u003e [1, 2, 3]\n```\n\nBut what about sorting scores inside of an object?\n\n```js\n[{a: 3}, {a: 1}, {a: 2}].sort();\n//\u003e [{a: 3}, {a: 1}, {a: 2}]\n```\n\nThat didn't work. Instead, you can write a custom `compareScore` function.\n\nA sort function takes two params, and compares the first to the second. It should return values saying where the second value should go in the array:\n\n  * -1 : sort to a lower index (front)\n  * 1 : sort to a higher index (back)\n  * 0 : stay the same\n\nAlright, now time to sort your best grades to the top.\n\nFirst you'll need to write a sort condition function called `compareScore`.\n\n##### Map\n\nArray -\u003e run a function over each item -\u003e Array\n\nYou've filtered and sorted our data, but neither of those actually change the data.\n\nWouldn't it be simpler if you could just change your grades?\n\nYou can use the array method `map` to run a function that returns changes to your data.\n\nAs an example, let's look at how you would increment each number in an array.\n\n```js\nfunction addOne(num) {\n  return num + 1;\n}\n\n[1, 2, 3].map(addOne);\n//\u003e [2, 3, 4]\n\nfunction addToVal(obj) {\n  obj.val += 1;\n  return obj;\n}\n[{ val: 1}].map(addToVal);\n//\u003e [{ val: 2 }]\n```\n\n`map` can change data, and it can also alter structure of the data you're working with.\n\n```js\nfunction makeObject(num) {\n  return { val: num };\n}\n\n[1, 2].map(makeObject);\n//\u003e [{ val: 1 }, { val: 2 }]\n```\n\nSimilarly, `map` can also restrict the data you want to work with.  See the example below to see another way scores could be sorted.\n\n```js\nmyBest\n  .map(function(student) {\n    return student.score;\n  })\n  .sort()\n  .reverse()\n//\u003e [93, 91, 88, 88, 82, 81, 73]\n```\n\nIn this example, `map` transformed an object with keys of 'title', 'instructor', 'name', 'score' and 'grade', to an array of just scores. Values weren't changed, but rather limited to a smaller subset of scores.\n\n`map` is powerful. Let's see what you can do with it.\n\nThose D \u0026 F grades would look a lot better if they suddenly became A's.\n\nLet's go back to before we filtered out the bad grades, and instead change the grades to A's.\n\n##### forEach\n\nArray -\u003e run a function for each item\n\nYou've updated your grades, but they're still in an array. It's time to loop over them and log them to the console.\n\nTo open the console, go to *View* \u003e *Developer* \u003e *Toggle Developer Tools*. Or press *cmd+opt+I* on Mac, *ctrl+alt+I* on Windows.\n\n`forEach` has a lot in common with `map`, but there is a big difference. Understanding that difference is important for grasping the difference between:\n\n  * **functional** \u0026 **imperative** programming\n  * **pure** \u0026 **impure** functions\n\nKnow it or not, you're probably already used to \"imperative\" programming.\n\n\u003e **Imperative** programming describes the order of actions\n\nImperative code tells the computer what to do, step by step.\n\n```js\nlet x = 1; // make a variable\nx = x + 1; // add one\nx = x + 1; // add another\nconsole.log(x);\n//\u003e 3\n```\n\n\u003e **Functional** programming describes the data transformation\n\nFunctional programming is a lot like writing math equations. As in math, 1 + 1 always equals 2.\n\nIn the same way, a **pure** function will always have the same result from a given input. Input 1 -\u003e output 2. Every time.\n\n```js\n// a pure function\nfunction addOne(x) {\n  return x + 1;\n}\naddOne(1)\n//\u003e 2\naddOne(1)\n//\u003e 2\n```\n\nA function is \"pure\" if it doesn't change anything outside of its scope. Pure functions are easy to test, reuse and reason about. In other words, they make your job easier.\n\nOn the other hand, **impure** functions are less predictable. The result may be different if you call it at a later time.\n\n```js\nlet y = 1;\n// impure function\nfunction increment(x) {\n  y += x;\n  return y;\n}\nincrement(1)\n//\u003e 2\nincrement(1)\n//\u003e 3\n```\n\nIt's good practice to ensure your `map` functions remain pure.\n\nBut `forEach` can be a little more dangerous. Why? Let's have a look.\n\n```js\n[1, 2, 3].map(addOne);\n//\u003e [2, 3, 4]\n\n[1, 2, 3].forEach(addOne);\n//\u003e undefined\n```\n\nWhat? `undefined`? `forEach` runs a function on each item in the array, and doesn't care what the function returns. Functions called by `forEach` must make changes, called **side effects**, to even be noticed.\n\n```js\n// impure function, changes log\nfunction addOneToLog(x) {\n  console.log(x);\n}\n\n[1, 2, 3].forEach(addOneToLog);\n//\u003e 2\n//\u003e 3\n//\u003e 4\n```\n\nNow that we see how `forEach` works, let's use it to make calls to the `console`.\n\n##### find\n\nArray -\u003e first element that matches a condition\n\nSomehow your name has disappeared from the computer system. We'll have to `find` a way to get it back.\n\nYou quickly put together a list of other students in class. If someone changed your name, it'll be the name that is not in that list.\n\n`find` works similar to `filter`, but returns only the first match.\n\n```js\nconst data = [1, 2, 3, 4, 5, 6];\n\nfunction isEven(num) {\n  return num % 2 === 0;\n}\n\n// returns all matching data to a condition\ndata.filter(isEven);\n//\u003e [2, 4, 6]\n\n// returns the first match\ndata.find(isEven);\n//\u003e [2]\n```\n\nFind is great for performantly matching unique values in data, such as an \"id\", or in our case: a name.\n\n##### concat\n\nArray + Array -\u003e Array\n\nBefore we've been working on a structured set of student data.\n\n```js\n// array of students\n[\n  {\n  \"title\": \"Relational Databases\",\n  \"instructor\": \"Sean Quentin Lewis\",\n  \"name\": \"Rebecca Heineman\",\n  \"score\": 71,\n  \"grade\": \"C\"\n  }\n// students in courses...\n]\n```\n\nTo be safe, let's now work on the original data set. Notice how it is structured differently.\n\n```js\n// array of courses\n[\n  {\n    \"title\": \"Relational Databases\",\n    \"instructor\": \"Sean Quentin Lewis\",\n    \"students\": [\n      {\n        \"name\": \"Rebecca Heineman\",\n        \"score\": 71,\n        \"grade\": \"C\"\n      }\n    // students...\n    ]\n  }\n  // courses...\n]\n```\n\nIn this data set, there is an array of students within an array of courses. So how can we recreate our original array of students from the courses?\n\nWeird things happen when you start combining arrays. We can use `concat` to bring sanity.\n\n```js\n[1, 2] + [3, 4];\n//\u003e \"1, 23, 4\"\n\n[1, 2].push([3, 4]);\n//\u003e 3\n\n[1, 2].join([3, 4]);\n//\u003e \"13, 42\"\n\n[1, 2].concat([3, 4]);\n//\u003e [1, 2, 3, 4]\n```\n\nUnfortunately, Javascript is missing a built in array method to concat multiple arrays together: let's call it `flatten` (sometimes called `concatAll`).\n\n`flatten` should loop over an array and `concat` each element.\n\nLet's look at an abstraction of what we need to do:\n\n```js\nconst start = [{\n  a: 1,\n  c: [\n    { b: 1 }\n  ]\n}, {\n  a: 2,\n  c: [\n    { b: 2 }, { b: 3 }\n  ]\n}];\n\nconst middle = start.map(function(outer) {\n  return outer.c.map(function(inner) {\n    return {\n      a: outer.a,\n      b: inner.b\n    };\n  });\n});\n//\u003e [ [{ a: 1, b: 1 }], [{a: 2, b: 2}, {a: 2, b: 3}] ]\n\nconst end = pre.flatten();\n//\u003e [{a: 1, b: 1}, {a: 2, b: 2}, {a: 2, b: 3}]\n```\n\nBack to business.\n\nWe have a suspect in mind: a classmate named \"Hack Kerr\". He's a nice guy, and he's always been friendly to you - but there's something suspicious about him: his name.\n\nWe'll test out flatten, then re-create our student array of data from the original course data.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoderoad%2Fcoderoad-functional-school-deprecated","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoderoad%2Fcoderoad-functional-school-deprecated","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoderoad%2Fcoderoad-functional-school-deprecated/lists"}