{"componentChunkName":"component---node-modules-gatsby-theme-chronoblog-src-templates-post-js","path":"/functional-lists/","result":{"data":{"mdx":{"id":"e0f0cc12-dab4-5b7e-8601-d68b5d6552ec","excerpt":"For my first post, I wanted to do something strange and entertaining. I don't want to bore you with super serious facts, or cover anything…","frontmatter":{"title":"Impractical, Functional Lists (List out of Lambda)","date":"2019-09-22T00:00:00.000Z","description":null,"tags":["post","fp","javascript"],"cover":null},"fields":{"slug":"/functional-lists/"},"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Impractical, Functional Lists (List out of Lambda)\",\n  \"date\": \"2019-09-22T00:00:00.000Z\",\n  \"tags\": [\"post\", \"fp\", \"javascript\"]\n};\n\nvar makeShortcode = function makeShortcode(name) {\n  return function MDXDefaultShortcode(props) {\n    console.warn(\"Component \" + name + \" was not imported, exported, or provided by MDXProvider as global scope\");\n    return mdx(\"div\", props);\n  };\n};\n\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"For my first post, I wanted to do something strange and entertaining. I don't want to bore you with super serious facts, or cover anything practical for that matter. Instead, we'll be walking through a programming exercise of sorts. The ideas in this post come from a topic in math called \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://en.wikipedia.org/wiki/Church_encoding\"\n  }), \"Church Encodings\"), \", and were inspired by another article, \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"http://stevelosh.com/blog/2013/03/list-out-of-lambda/\"\n  }), \"List out of Lambda\"), \".\"), mdx(\"h2\", {\n    \"id\": \"introduction\"\n  }, \"Introduction:\"), mdx(\"p\", null, \"The goal of today is to rebuild language functionality using a VERY limited tool set. Sort of a \\\"build a lot with a little\\\" puzzle. We'll be creating a Javascript list data structure using \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"nothing\"), \" but functions.\"), mdx(\"h2\", {\n    \"id\": \"part-1-closures\"\n  }, \"Part 1: Closures\"), mdx(\"p\", null, \"An important prerequisite to understanding the contents of this post is knowing a bit about Javascript functions. More specifically, you will need to understand how closures work. If you feel comfortable with closures go ahead and move on to Part 2! If not, no worries! We'll cover them in good detail, and if you're still confused by the end of the explanation, I'll link you to resources that explain things better than I did. I won't beat around the bush anymore. Let's answer the question: What is a closure?\"), mdx(\"p\", null, \"In developer speak, a closure is the combination of a function and the lexical environment within which that function was declared. \"), mdx(\"p\", null, \"You can think about it this way; all Javascript functions are closures. Javascript functions all contain a reference to their outer environment.\"), mdx(\"p\", null, \"For example:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"let bar = 1\\nfunction foo() {\\n    console.log(\\\"bar = \\\", bar)\\n}\\nfoo() // \\\"bar = 1\\\"\\n\")), mdx(\"p\", null, \"In this snippet of code, we have a function \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"foo\"), \" that logs out some value \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"bar\"), \". Because functions in Javascript have a reference to their outer scope, we can access the variable \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"bar\"), \" from inside our function \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"foo\"), \".\"), mdx(\"p\", null, \"This functionality is pretty standard though, right? Functions having access to the global scope is supported in almost every programming language. \"), mdx(\"p\", null, \"Closures get much more interesting when our language supports first-class functions. First-class meaning that our functions can be treated as regular values. This gives us a few new capabilities.\"), mdx(\"p\", null, \"We can...\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Assign functions to variables\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Pass functions as arguments to other functions\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Return functions from other functions\")), mdx(\"p\", null, \"Consider the case when a function returns a function. As we've discussed, all Javascript functions are closures. This means our returned function has access to the full environment in which it was declared. So, our returned function has access to everything that is declared inside the outer function!\"), mdx(\"p\", null, \"Here's an example that might help:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"function lineByLine() {\\n    const name = \\\"LineXLine\\\"\\n    const authors = [\\\"ben\\\", \\\"jon\\\", \\\"clayton\\\"]\\n    return function() {\\n        return name + \\\" team: \\\" + authors.join()\\n    }\\n}\\n\\nconst getTeamInfo = lineByLine()\\n\\ngetTeamInfo()\\n=> \\\"linexline team: ben,jon,clayton\\\"\\n\")), mdx(\"p\", null, \"By returning a function from within a function, you not only get the returned function when called, but the returned function also gets access to its outer environment at the time it was created. The function \\\"closes\\\" in on it's outer environment, hence closures :)\"), mdx(\"p\", null, \"We'll look at one more example for good measure.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"function idGenerator(idPrefix) {\\n    let suffix = 0\\n    return function() {\\n        const id = idPrefix + suffix\\n        suffix += 1\\n        return id\\n    }\\n}\\n\\nconst getCatId = idGenerator(\\\"cat\\\")\\ngetCatId() // => \\\"cat0\\\"\\ngetCatId() // => \\\"cat1\\\"\\ngetCatId() // => \\\"cat2\\\"\\n\")), mdx(\"p\", null, \"Here we've written at function called \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"idGenerator\"), \". It takes some prefix string as an argument and returns a function.\\nThe returned function returns to us an incremented ID upon each call.\\nLet's walk through it in some detail. We assign \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"getCatId\"), \" to the function returned by \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"idGenerator(\\\"cat\\\")\"), \". When I call the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"getCatId\"), \" function, it generates a new id by appending the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"idPrefix\"), \" with the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"suffix\"), \" that is assigned inside the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"idGenerator\"), \" function. After it generates a new code, we've incremented the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"suffix\"), \" count so the next time we invoke the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"getCatId\"), \" function, we'll get a different cat id.\"), mdx(\"p\", null, \"This example shows off another cool feature of closures. Not only can you read from\\nthe returned function's outer environment, but you can mutate it. If you come from a background of object oriented programming, you can think of \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"suffix\"), \" as a private variable. I can't access \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"suffix\"), \" outside the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"idGenerator\"), \" function directly, but I was able to return a function that can!\"), mdx(\"p\", null, \"I actually got this as an interview question a couple years ago. Very easy to solve if you understand closures - quite complex if you rely on global shared state.\"), mdx(\"p\", null, \"If these examples sufficed and you feel comfortable with closures in Javascript, let's move on! If not feel free to take a look at the resources below. It's worth the time to learn this thoroughly especially if you use Javascript on a regular basis.\"), mdx(\"p\", null, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://developer.mozilla.org/en-US/docs/Web/Javascript/Closures\"\n  }), \"https://developer.mozilla.org/en-US/docs/Web/Javascript/Closures\")), mdx(\"p\", null, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://blog.bitsrc.io/a-beginners-guide-to-closures-in-Javascript-97d372284dda\"\n  }), \"https://blog.bitsrc.io/a-beginners-guide-to-closures-in-Javascript-97d372284dda\")), mdx(\"p\", null, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://www.youtube.com/watch?v=F3EsDDp4VXg\"\n  }), \"https://www.youtube.com/watch?v=F3EsDDp4VXg\")), mdx(\"hr\", null), mdx(\"h2\", {\n    \"id\": \"part-2-lets-build-a-list\"\n  }, \"Part 2: Let's build a list\"), mdx(\"p\", null, \"What if Javascript didn't provide us with a list-like structure? No arrays, no objects. Is it possible to build our own?\"), mdx(\"p\", null, \"First, let's build some criteria of what this list structure should provide.\"), mdx(\"p\", null, \"Wish List (pun intended):\"), mdx(\"p\", null, \"1) We need some concept of an empty list.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"isEmpty([]) // true\\n\")), mdx(\"p\", null, \"2) We need to be able to prepend items to an existing list.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"prepend(1, [2, 3]) // [1, 2, 3]\\n\")), mdx(\"p\", null, \"3) We need to be able to get the head and tail of a list. (\", mdx(\"em\", {\n    parentName: \"p\"\n  }, \"Head being the first element of a list and tail being a list of everything but the first element\"), \")\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"head([1, 2, 3]) //1\\ntail([1, 2, 3]) // [2, 3]\\n\")), mdx(\"p\", null, \"Here is some blueprinting of the functions that we'll be implementing, and some examples of how they'll be used.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"const empty = //TODO\\n\\nfunction isEmpty(list) {\\n  //TODO\\n}\\n\\nfunction prepend(head, tail) {\\n  //TODO\\n}\\n\\nfunction head(list) {\\n  //TODO\\n}\\n\\nfunction tail(list) {\\n  //TODO\\n}\\n\\n/** Example Usage */\\n\\nconst fruitBasket = prepend(\\\"apple\\\", prepend(\\\"orange\\\", prepend(\\\"banana\\\", empty)));\\n\\nconst isEmptyFruitBasket = isEmpty(fruitBasket) // false\\n\\nconst firstFruit = head(fruitBasket)    // \\\"apple\\\"\\n\\nconst leftovers = tail(fruitBasket) // prepend(\\\"orange\\\", prepend(\\\"banana\\\", empty))\\n\\n\")), mdx(\"p\", null, \"Our end goal is to implement all of this with nothing but functions, but for now, let's try implementing this with all tools at our disposal (aside from arrays & objects) and try removing them one by one.\"), mdx(\"p\", null, \"We'll start with the basics: the empty list. How will we define the empty list? \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"null\"), \" seems appropriate for the time being. With that in mind, we can implement a couple of our \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"TODO\"), \"s\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"const empty = null\\n\\nfunction isEmpty(list) {\\n  return list === empty\\n}\\n\\nfunction prepend(head, tail) {\\n  //TODO\\n}\\n\\nfunction head(list) {\\n  //TODO\\n}\\n\\nfunction tail(list) {\\n  //TODO\\n}\\n\")), mdx(\"p\", null, \"Now, let's implement \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"prepend\"), \". This is the hardest function to wrap your head around. Take a minute to read the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"prepend\"), \"implementation below, and think of how you might write \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"head\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"tail\"), \". The goal of \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"prepend\"), \" is to add an element to the beginning of an existing list and return it. If you get stuck trying to understand \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"prepend\"), \", move on to the next part - it provides some more context on how \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"prepend\"), \" is used.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"const empty = null\\n\\nfunction isEmpty(list) {\\n  return list === empty\\n}\\n\\n// head will be the element to prepend to another list, tail.\\nfunction prepend(head, tail) {\\n  return function(option) {\\n    if(option === \\\"head\\\") {\\n      return head\\n    }\\n    else if (option === \\\"tail\\\") {\\n      return tail\\n    }\\n  }\\n}\\n\\nfunction head(list) {\\n  //TODO\\n}\\n\\nfunction tail(list) {\\n  //TODO\\n}\\n\")), mdx(\"p\", null, \"The key take away from this is that \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"prepend\"), \" returns a function. Earlier, I said that \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"prepend\"), \" should return a list. So where is the list? The function returned IS our list. In reality, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"prepend\"), \" isn't actually creating a list. Instead, it's just gluing two things together and storing them in a closure. BUT, we can still treat this as a list.\"), mdx(\"p\", null, \"Let's think back to the criteria for our list - the only operations we really need are grabbing the head, tail, and prepending a new element to our list. We can do that with this returned function!\"), mdx(\"p\", null, \"Wanna see how?\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"// create a list of farm animal sounds\\nconst farm_animal_sounds = prepend(\\\"moo\\\", prepend(\\\"oink\\\", empty))\\n\\n// grab the first element\\nconst head_element = farm_animal_sounds(\\\"head\\\") // => \\\"moo\\\"\\n\\n// grab everything after the first element\\nconst tail_elements = farm_animal_sounds(\\\"tail\\\") // => prepend(\\\"oink\\\", empty)\\n\\n// create a new list by prepending \\\"woof\\\" to our old list\\nconst more_animal_sounds = prepend(\\\"woof\\\", farm_animal_sounds)\\n\")), mdx(\"p\", null, \"A little confused? Remember that our \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"prepend\"), \" function returns a function. The returned function accepts an option argument of either \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"\\\"head\\\"\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"\\\"tail\\\"\"), \" and returns the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"head\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"tail\"), \" as they were specified in the outer \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"prepend\"), \" function's arguments. It's a simple idea, but very unfamiliar and difficult to wrap your head around, so don't worry if it isn't crystal clear yet. \"), mdx(\"p\", null, \"It's time to move on and implement our \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"head\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"tail\"), \" functions. This should be straight forward now because we've basically wrote the code for them already.\"), mdx(\"p\", null, \"For now, we won't worry about error cases (calling head and tail on the empty list). So, assuming our head and tail functions receive an unempty list, let's return the head and tail respectively.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"function head(list) {\\n    return list(\\\"head\\\")\\n}\\n\\nfunction tail(list) {\\n  return list(\\\"tail\\\")\\n}\\n\")), mdx(\"p\", null, \"That's it! We just invoke the list function with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"\\\"head\\\"\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"\\\"tail\\\"\"), \". We have all the functions we set out to create! We'll call this our version 1 list implementation.\"), mdx(\"p\", null, \"So, we have a list, but where is the data stored? The values are actually being stored inside nested closures. Each call to prepend returns a closure that has a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"head\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"tail\"), \" value captured in its scope.\"), mdx(\"p\", null, \"To get a little more familiar with how our lists work, let's write some helper functions for them.\"), mdx(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"Quick Aside:\\nIf you'd like to do some playing around with these lists but don't want to keep typing all the prepend calls, just use this function for some quick list creation.\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"const createList = (...args) => args.reverse().reduce((acc, el) => prepend(el, acc), empty)\\n\\n// Usage:\\nconst disappointing_movies = createList(\\\"Shrek 3\\\",\\n                                        \\\"Mighty Ducks 3\\\",\\n                                        \\\"The Last Airbender\\\",\\n                                        \\\"Eragon\\\")\\n\")), mdx(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"ok, back to the helper functions...\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"function length(list) {\\n  //TODO\\n}\\n\\nfunction map(f, list) {\\n  //TODO\\n}\\n\\nfunction filter(predicate, list) {\\n  //TODO\\n}\\n\\n/** Example Usage */\\n\\nconst nums = createList(1, 2, 3, 4, 5)\\n// => (1, 2, 3, 4, 5)\\n\\nconst len = length(nums) \\n// => 5\\n\\nconst doubled_nums = map(function(x) { return x * 2 }, nums)\\n// => (2, 4, 6, 8, 10)\\n\\nconst big_nums = filter(function(x) { return x > 3 }, nums)\\n// => (4, 5)\\n\")), mdx(\"p\", null, \"Implementations:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"\\nfunction length(list) {\\n  if(isEmpty(list)) {\\n    return 0;\\n  }\\n  else {\\n    return 1 + length(tail(list))\\n  }\\n}\\n\\nfunction map(f, list) {\\n  if(isEmpty(list)) {\\n    return list;\\n  }\\n\\n  const h = head(list)\\n  const t = tail(list)\\n\\n  return prepend(f(h), map(f, t));\\n}\\n\\nfunction filter(predicate, list) {\\n    if(isEmpty(list)) {\\n        return list;\\n    }\\n    const h = head(list)\\n    const t = tail(list)\\n    \\n    if(predicate(h)) {\\n        return prepend(h, filter(predicate, t))\\n    }\\n    else {\\n        return filter(predicate, t)\\n    }\\n}\\n\")), mdx(\"p\", null, \"Take time to use some of these list helpers or maybe write a few new list helpers to get you more comfortable with the lists we've made.\"), mdx(\"p\", null, \"List Helper Suggestions:\"), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"printList\"), \" - takes a list and prints each item\"), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"sum\"), \" - takes a list of numbers and returns their sum\"), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"reverse\"), \" - takes a list and returns a reversed version of the list\"), mdx(\"h2\", {\n    \"id\": \"part-3-removing-strings\"\n  }, \"Part 3: Removing Strings\"), mdx(\"p\", null, \"Our current list structure works, but we're using a bit of unneeded language functionality.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Current Tool Box:\")), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"functions\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"strings\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"booleans/equality expressions\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"if/else statements\")), mdx(\"p\", null, \"Let's start by removing the usage of strings inside our list implementation.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"const empty = null\\n\\nfunction isEmpty(list) {\\n  return list === empty\\n}\\n\\nfunction prepend(head, tail) {\\n  return function(select) {\\n    return select(head, tail)\\n  }\\n}\\n\\nfunction head(list) {\\n  return list(function(head, tail) {\\n    return head\\n  })\\n}\\n\\nfunction tail(list) {\\n  return list(function(head, tail) {\\n    return tail\\n  })\\n}\\n\")), mdx(\"p\", null, \"We're done! No more strings! \"), mdx(\"p\", null, \"This code change wasn't too large, but it deserves an explanation. All the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"head\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"tail\"), \" functions need is access to the actual head and tail of a list. In our case, lists are just functions, so we can give our list a select function that we can call with the values of head and tail.\"), mdx(\"p\", null, \"If this isn't making any sense, I would suggest stepping through an example to see how it works. It's very helpful to write this out on paper for yourself, but I'll try my best to go step by step through an example.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"const tear_worthy_movies = prepend(\\\"Cast Away\\\", empty)\\nhead(tear_worthy_movies)\\n// => \\\"Cast Away\\\"\\n\")), mdx(\"p\", null, \"Walkthrough: \"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"// Line 1\\nconst myList = prepend(\\\"Cast Away\\\", empty)\\n\")), mdx(\"hr\", null), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"// Reduction of the prepend call in Line 1\\nconst myList = function(op) {       \\n  return op(\\\"Cast Away\\\", empty)\\n}\\n\")), mdx(\"hr\", null), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"// Line 2\\nhead(myList)\\n\")), mdx(\"hr\", null), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"// Expanding the head function from Line 2\\n(function(list){\\n  return list(function(head, tail) {\\n    return head;\\n  })\\n})(myList)\\n\")), mdx(\"hr\", null), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"// Reduction of Step 4\\nmyList(function(head, tail) {\\n   return head\\n})\\n\")), mdx(\"hr\", null), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"// Expanding the myList function \\n(function(op) {\\n  return op(\\\"Cast Away\\\", empty)\\n})(function(head, tail) {\\n   return head\\n})\\n\")), mdx(\"hr\", null), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"// Reduction of Step 6\\n (function(head, tail) { return head })(\\\"Cast Away\\\", empty)\\n\")), mdx(\"hr\", null), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"// Final Reduction\\n \\\"Cast Away\\\"\\n\")), mdx(\"p\", null, \"That was a lot of logic to trace through. If you're still confused about how this works, take your time reading over the steps again, or try your own example on paper. You will need a good understanding of this section before moving on to the next one.\"), mdx(\"h2\", {\n    \"id\": \"part-4-removing-ifelse\"\n  }, \"Part 4: Removing If/Else\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Updated Tool Box:\")), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"functions\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"booleans/equality expressions\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"if/else statements\")), mdx(\"p\", null, \"Let's remove those if/else statements.\"), mdx(\"p\", null, \"Currently if/else statements are only being used to test if a list is empty. One way to avoid this is to tag each list as being empty or not being empty. To do this, we have to make a couple changes.\"), mdx(\"p\", null, \"First, we will have to add a new parameter to our \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"selector\"), \" function that determines if a list is empty or not.\"), mdx(\"p\", null, \"Next, the value of the empty list can no longer just be \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"null\"), \". We'll need to assign a list function to our \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"empty\"), \" value that tags the list as being empty.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"const empty = function(select) {\\n  return select(null, null, true)\\n}\\n\\nfunction isEmpty(list) {\\n  return list(function(head, tail, isempty) {\\n    return isempty\\n  })\\n}\\n\\nfunction prepend(head, tail) {\\n  return function(select) {\\n    return select(head, tail, false)\\n  }\\n}\\n\\nfunction head(list) {\\n  return list(function(head, tail, isempty) {\\n    return head\\n  })\\n}\\n\\nfunction tail(list) {\\n  return list(function(head, tail, isempty) {\\n    return tail\\n  })\\n}\\n\")), mdx(\"h2\", {\n    \"id\": \"part-5-removing-booleans\"\n  }, \"Part 5: Removing Booleans\"), mdx(\"p\", null, \"We've come quite a long way since version 1, but more work can still be done. We need to remove those booleans. How can we do this though? Ultimately, we need some way to determine if a list is empty, which means we need a way to run conditional expressions. Let's try rewriting conditionals using functions. Sounds a bit daunting, but it's doable.\"), mdx(\"p\", null, \"Once again, we need to think of things very abstractly here. What is the core functionality we NEED to make our conditionals work?\"), mdx(\"p\", null, \"1.) Need to provide constants for both true and false\"), mdx(\"p\", null, \"2.) Need to use these constants to choose between two things (essentially \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"if/else\"), \" statements)\"), mdx(\"p\", null, \"We're going to write our true and false values as functions that choose between two things.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"function truthy(t, f) {\\n  return t\\n}\\n\\nfunction falsey(t, f) {\\n  return f\\n}\\n\")), mdx(\"p\", null, \"Our function truthy takes two things and always returns the first, and our falsey function takes two things and always returns the latter.\"), mdx(\"p\", null, \"How are these going to be used as true and false values?\"), mdx(\"p\", null, \"Without much context, these don't make a lot of sense, but the implementation of \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ifelse\"), \" should shine a bit of light on the answer.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"function ifelse(conditional, then, else) {\\n  return conditional(then, else)\\n}\\n\")), mdx(\"p\", null, \"The conditional that is passed into \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ifelse\"), \" will always be either \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"truthy\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"falsey\"), \".\"), mdx(\"p\", null, \"Example:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"const a = ifelse(truthy, 1, 2)  \\n// => 1\\n\\nconst b = ifelse(falsey, \\\"it was TRUE!\\\", \\\"sorry... it was false.\\\") \\n// => \\\"sorry.. it was false.\\\"\\n\")), mdx(\"p\", null, \"We just wrote if/else functionality with nothing but Javascript functions!\"), mdx(\"p\", null, \"Great, but how do we apply this to our lists?\\nWe should just be able to replace the usages of true and false with truthy and falsey.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"const empty = function(select) {\\n  select(null, null, truthy)\\n}\\n\\nfunction isEmpty(list) {\\n  return list(function(head, tail, isempty) {\\n    return isempty\\n  })\\n}\\n\\nfunction prepend(head, tail) {\\n  return function(op) {\\n    return op(head, tail, falsey)\\n  }\\n}\\n\\nfunction head(list) {\\n  return list(function(head, tail, isempty) {\\n    return head\\n  })\\n}\\n\\nfunction tail(list) {\\n  return list(function(head, tail, isempty) {\\n    return tail\\n  })\\n}\\n\")), mdx(\"p\", null, \"This begs the question though: Why did we write \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ifelse\"), \"?\"), mdx(\"p\", null, \"It isn't super obvious, but we need it for \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"isEmpty\"), \" to be usable inside our other list helper functions. Our old implementations of things like \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"length\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"map\"), \", and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"filter\"), \" relied on our old implementation of \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"isEmpty\"), \". That implemenation doesn't work anymore because Javascript's native if/else statements won't work with our \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"truthy\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"falsey\"), \" values.\"), mdx(\"p\", null, \"Time for a \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"refactor\"), \"!\"), mdx(\"p\", null, \"Let's implement length again using our newly formed lists.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"function length(list) {\\n  return ifelse(isEmpty(list),\\n              0,\\n              1 + length(tail(list)))\\n}\\n\")), mdx(\"p\", null, \"Seems like a reasonable and simple solution. Unfortunately, there is a problem. The problem is one we can't avoid because it is engrained at the language level of Javascript.\"), mdx(\"p\", null, \"To find the problem imagine we called length on the empty list.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"length(empty)\\n\")), mdx(\"p\", null, \"The above line will produce the following:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"ifelse(isEmpty(list),\\n         0,\\n         1 + length(tail(list)))\\n\\n\")), mdx(\"p\", null, \"Even though our list is empty and the only branch that should execute is the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"0\"), \", the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"1 + length(tail(list))\"), \" will still be run because \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ifelse\"), \" is just a function and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"1 + length(tail(list))\"), \" is an argument we've given to that function. In short, the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"1 + length(tail(list))\"), \" will be evaluated regardless of the outcome of \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"isEmpty(list)\"), \", and when this happens we'll be attempting to get the tail of an empty list which can't be done.\"), mdx(\"p\", null, \"So, how can we avoid this issue? How do we postpone execution until we must execute a specific branch of the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ifelse\"), \" function? The answer to this question is the same as the answer to almost every question asked so far: functions!\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"function length(list) {\\n  const zero = function() {\\n    return 0\\n  }\\n\\n  const tail_length = function() {\\n    return 1 + length(tail(list))\\n  }\\n\\n  return ifelse(isEmpty(list), zero, tail_length)\\n}\\n\")), mdx(\"p\", null, \"This also requires us to change our original booleans as well from this:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"function truthy(t, f) {\\n  return t\\n}\\n\\nfunction falsey(t, f) {\\n  return f\\n}\\n\")), mdx(\"p\", null, \"to this:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"function truthy(t, f) {\\n  return t()\\n}\\n\\nfunction falsey(t, f) {\\n  return f()\\n}\\n\")), mdx(\"p\", null, \"Which leaves us with our final implementation for our functional lists:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-javascript\"\n  }), \"function truthy(t, f) {\\n  return t()\\n}\\n\\nfunction falsey(t, f) {\\n  return f()\\n}\\n\\nfunction ifelse(conditional, then, else) {\\n  return conditional(then, else)\\n}\\n\\nconst nil = function() {} // added this for the sake of completion\\n\\nconst empty = function(select) {\\n  select(nil, nil, truthy)\\n}\\n\\nfunction isEmpty(list) {\\n  return list(function(h, t, e) {\\n    return e\\n  })\\n}\\n\\nfunction prepend(head, tail) {\\n  return function(select) {\\n    return select(head, tail, falsey)\\n  }\\n}\\n\\nfunction head(list) {\\n  return list(function(head, tail, e) {\\n    return head\\n  })\\n}\\n\\nfunction tail(list) {\\n  return list(function(head, tail) {\\n    return tail\\n  })\\n}\\n\")), mdx(\"p\", null, \"We've finally arrived at our end goal! This is a list data structure using nothing but Javascript functions. Mess around with this more, and see what other language functionality you can create by using functions (let expressions, loops, numbers, etc.). Below is a link to a repo that contains all the code I've shown here along with some additional list helpers and an ES6 refactor if you're interested.\"), mdx(\"p\", null, \"Hopefully this exercise forced you to think a little differently and didn't cause too much frustration. Trying to build something with very limited tool sets often leads to very creative solutions that you wouldn't be exposed to in your day-to-day programming.\"), mdx(\"p\", null, \"Thanks for reading!\"), mdx(\"p\", null, \"Functional List Implementation: \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://github.com/claytn/Playground/tree/master/LineXLine/ListOutOfLambda\"\n  }), \"https://github.com/claytn/Playground/tree/master/LineXLine/ListOutOfLambda\")));\n}\n;\nMDXContent.isMDXComponent = true;"}},"pageContext":{"id":"e0f0cc12-dab4-5b7e-8601-d68b5d6552ec"}}}