text: (window.webpackJsonp=window.webpackJsonp||[]).push([[3],{497:function(e,t,n){"use strict";n.r(t);var a=n(54),o=n.n(a),i=n(1),l=n.n(i),r=n(4),s=n(27),c=n(29),u=n(34),m=n(104),p=n(42),d=n(11),g=n(40),f=n(22),h=n(62),y=[{name:"Improve your programming skills"},{name:"Enjoy high-speed performance"},{name:"Write shorter code"},{name:"KISS functional programming"},{name:"Inversion of control and dependency injection"},{name:"Enjoy programming more"}],E=function(e){return"lambda-"+Object(f.c)(e)};t.default=function(){var e=Object(i.useState)(!1),t=o()(e,2),n=t[0],a=t[1];return Object(i.useEffect)((function(){return window.addEventListener("scroll",(function(){return window.pageYOffset>0?a(!0):a(!1)}))}),[]),l.a.createElement(s.a,null,l.a.createElement("header",{className:"whiteBackground"},l.a.createElement(r.i,null,l.a.createElement("h1",null,l.a.createElement("div",null,l.a.createElement("strong",null,"@7urtle"),"/lambda"),"JavaScript functional programming advantages"))),l.a.createElement("article",{className:"whiteBackground textLeft pb6 plr1"},l.a.createElement(r.i,null,l.a.createElement(r.t,null,l.a.createElement(r.g,{md:"3",className:"LearnSideMenu d-none d-md-block"},l.a.createElement("p",null,l.a.createElement(g.a,{target:d.b.Learn},"‹ Learn")),l.a.createElement("h2",{className:"pt-0"},"JavaScript functional programming advantages"),l.a.createElement(p.a,{contents:y,sorted:!1})),l.a.createElement(r.g,null,l.a.createElement("p",null,"Learning ",l.a.createElement("strong",null,"functional programming")," improves all of your programming skills. It teaches you about general best practices for programming like inversion of control or the single responsibility principle. It also helps you write shorter, more reusable, and performant code. Not to mention that for many developers writing in a functional style is just more fun."),l.a.createElement("p",null,l.a.createElement("strong",null,"Functional programming")," is not a new thing. It is a ",l.a.createElement("strong",null,"declarative programming paradigm")," based on ",l.a.createElement("strong",null,"lambda calculus")," from 1930s. In 1937, ",l.a.createElement("strong",null,"Alan Turing"),"  himself proved that lambda calculus and Turing machines are equivalent computational systems. You don't need to learn any of the underlying mathematics but the math is there to make your coding easier. First functional programming language, ",l.a.createElement("strong",null,"LISP"),", was developed in 1950s. You can read about how ",l.a.createElement("a",{href:"http://www.paulgraham.com/avg.html",target:"_blank"},"LISP influenced early Yahoo"),". 70 years later, functional programming principles made their way into all major imperative object-oriented languages including ",l.a.createElement("strong",null,"Java"),", ",l.a.createElement("strong",null,"C#"),", or ",l.a.createElement("strong",null,"Python"),"."),l.a.createElement("p",null,l.a.createElement("strong",null,"JavaScript")," through its support of ",l.a.createElement(g.a,{target:d.b.LambdaBasics},"first-class functions")," is ideal for you to take ",l.a.createElement("strong",null,"advantage of functional programming"),"."),l.a.createElement("h2",{className:"pt-2",id:E(y[0].name)},y[0].name),l.a.createElement("p",null,"It is important to know programming best practice to develop robust solution that will survive into the future. Following best practices has always required continuous study of programming as well discipline to apply in your code. ",l.a.createElement("strong",null,"Functional programming")," is different in a sense that it is designed to lead you towards those practices without you having to always be conscious and disciplined about it."),l.a.createElement("p",null,"You might be surprised how effortless it becomes to shorter and faster code that is easy to understand and test."),l.a.createElement("h3",{id:E(y[1].name)},y[1].name),l.a.createElement("p",null,"Well designed functional code can be surprisingly easy to make super performant. We are building code based on pure functions. This functions always provide the same output for the same input. Composition is just many of these functions in a line and therefore the input at the beginning again returns the same output."),l.a.createElement("p",null,"You can use this functional purity by leveraging caching mechanisms for memoization. Basically you map input of complex functions directly to their output skipping all the computation. With ",l.a.createElement("strong",null,"@7urtle/lambda")," it is super simple thanks to its function ",l.a.createElement("code",null,"memo"),":"),l.a.createElement(u.a,{language:"javascript",code:"import {memo} from '@7urtle/lambda';\n\nconst complexCompose = compose(lots of pure functions);\n\nconst memoCompose = memo(complexCompose);\n\nmemoCompose('input'); // executed once for the input\nmemoCompose('input'); // not executed, returns result directly"}),l.a.createElement("p",null,"The same function ",l.a.createElement("code",null,"memo")," will be also used in the ",l.a.createElement("strong",null,"functional programming")," example in the next section."),l.a.createElement("h3",{id:E(y[2].name)},y[2].name),l.a.createElement("p",null,"In experience of functional programmers, functionally written code is generally much shorter. In ",l.a.createElement("strong",null,"JavaScript")," that's of course supported by a shorter syntax for arrow functions, but the more important difference is cause by better reusability and modularity of the code. In short, ",l.a.createElement("strong",null,"functional programming")," makes your code more clever and shorter."),l.a.createElement("p",null,"For an example consider this advanced functional code:"),l.a.createElement(u.a,{language:"javascript",code:"import {Maybe, liftA3, memo} from '@7urtle/lambda';\n\nconst getTargetOffsetTopMaybe = memo(input => Maybe.of(document.querySelector(input)).map(a => a.offsetTop));\nconst getClientHeightMaybe = memo(input => Maybe.of(document.querySelector(input)).map(a => a.clientHeight));\nconst getPositionMaybe = memo(input =>\n    liftA3\n    (TargetOffsetTop => ArticleOffsetTop => MainMenuClientHeight => TargetOffsetTop + ArticleOffsetTop - MainMenuClientHeight - 28)\n    (getTargetOffsetTopMaybe(input))\n    (getTargetOffsetTopMaybe('article'))\n    (getClientHeightMaybe('.MainMenu')));\n    \nconst MaybePosition = getPositionMaybe('#someElement');\nMaybePosition.isNothing() ? 'one of the elements may not exist' : 'position is ' + MaybePosition.value;"}),l.a.createElement("p",null,"These 3 functions on 8 lines of code read the positions and sized of DOM elements on a page to calculate a position that would be later used for smooth scrolling animation. We are using monads ",l.a.createElement("code",null,"Maybe")," because DOM represents a side effect and those elements simply may not exist. We use these monads as applicatives in ",l.a.createElement("code",null,"liftA3")," to safely calculate the position returning another ",l.a.createElement("code",null,"Maybe")," monad. In the whole code that executes the animation we would not need to use any conditions or error handling because everything is elegantly taken care of by the magic of functional programming. As a bonus , because we don't want repeated calculation, the ",l.a.createElement("code",null,"memo")," function takes care of caching, so each unique element is calculated only once."),l.a.createElement("p",null,"Imperative code doing the same thing using more than three times as many lines to define only ",l.a.createElement("code",null,"getPosition")," would look like this:"),l.a.createElement(u.a,{language:"javascript",code:"let ArticleOffsetTop = 0;\nlet MainMenuClientHeight = 0;\nlet cache = {};\n\nconst getPosition = function (input) {\n  if (input in cache) {\n    return cache[input];\n  }\n\n  const target = document.querySelector(input);\n  \n  if(ArticleOffsetTop === 0) {\n    const article = document.querySelector('article');\n    if(article !== undefined) {\n      ArticleOffsetTop = article.offsetTop;\n    }\n  }\n  \n  if(MainMenuClientHeight === 0) {\n    mainMenu = document.querySelector('.MainMenu');\n    if(mainMenu !== undefined) {\n      MainMenuClientHeight = mainMenu.clientHeight;\n    }\n  }\n  \n  if(target !== undefined && ArticleOffsetTop !== 0 && MainMenuClientHeight !== 0) {\n    const TargetOffsetTop = target.offsetTop;\n    const result = TargetOffsetTop + ArticleOffsetTop - MainMenuClientHeight - 28;\n    cache[input] = result;\n    return result;\n  } else {\n    cache[input] = undefined;\n    return undefined;\n  }\n};\n\nconst position = getPosition('#someElement');\n\nif(position === undefined) {\n  'one of the elements may not exist';\n} else {\n  'position is ' + position;\n}"}),l.a.createElement("h3",{id:E(y[3].name)},y[3].name),l.a.createElement("p",null,l.a.createElement("strong",null,"KISS")," means ",l.a.createElement("strong",null,"Keep It Simple Stupid")," and it is a principle that says that ",l.a.createElement("em",null,"simple code design should be always preferred"),". It is similar to the single responsibility principle that states: ",l.a.createElement("em",null,"Every function should have responsibility over a single part of the functionality.")," One function should do one thing."),l.a.createElement("p",null,l.a.createElement("strong",null,"Functional programming")," helps you to write ",l.a.createElement("strong",null,"easily testable and highly reusable functions"),". It breaks your code into small simple pieces that you can compose into more and more powerful pieces. Because of that you will be able to understand your colleagues' as well as your own code more easily. At the same time it will be effortless to ",l.a.createElement(g.a,{target:d.b.Testing},"painlessly build test coverage"),"."),l.a.createElement("p",null,"If you goal was to write a function that always trims its input and turns it into upper case shouting, you would likely write it like this in imperative code:"),l.a.createElement(u.a,{language:"javascript",code:"const shout = function (input) {\n  input = input.trim().toUpperCase();\n  const lastLetter = input.substr(-1);\n  \n  if ('.?!,'.includes(lastLetter)) {\n    input = input.substr(0, input.length -1) + '!';\n  } else {\n    input = input + '!';\n  }\n\n  return input;\n};\n\nshout(\" Don't forget to feed the turtle.\"); // => DON'T FORGET TO FEED THE TURTLE!"}),l.a.createElement("p",null,"It is natural to focus on the overall task which is to build a function that does what we want and build a full function that delivers on the task. It takes discipline then to realize how to break the function down into its ",l.a.createElement("strong",null,"single responsibility")," parts."),l.a.createElement("p",null,"This is also a reason why ",l.a.createElement("strong",null,"defensive programming")," is asking you to write a test for every step of your code. Large functions and classes have a tendency to hide a lot of internal logic if your unit test focuses only on a simple test of their output."),l.a.createElement("p",null,"Now let's write the same function using ",l.a.createElement("strong",null,"@7urtle/lambda")," and ",l.a.createElement(g.a,{target:d.b.LambdaBasics},"functional programming principles of function composition"),"."),l.a.createElement(u.a,{language:"javascript",code:"import {trim, upperCaseOf, lengthOf, lastLetterOf, includes, compose} from '@7urtle/lambda';\n\nconst endsWithPunctuation = input => includes(lastLetterOf(input))('.?,!');\nconst replacePunctuationWithExclamation = input => substr(lengthOf(input) - 1)(0)(input) + '!';\nconst addExclamationMark = input => endsWithPunctuation(input) ? replacePunctuationWithExclamation(input) : input + '!';\n\nconst shout = compose(addExclamationMark, upperCaseOf, trim);\n\nshout(\" Don't forget to feed the turtle.\"); // => DON'T FORGET TO FEED THE TURTLE!"}),l.a.createElement("p",null,"The functional code follows the principle of ",l.a.createElement("strong",null,"single responsibility")," and we end up with four easily testable and highly reusable functions ",l.a.createElement("code",null,"endsWithPunctuation"),", ",l.a.createElement("code",null,"replacePunctuationWithExclamation"),", ",l.a.createElement("code",null,"addExclamationMark"),", and ",l.a.createElement("code",null,"shout"),". When you look at the function ",l.a.createElement("code",null,"shout"),", it is easy to deduce that the function return trimmed upper-case of its input with an exclamation mark. In the original code you have to read to whole function to understand what it does."),l.a.createElement("h3",{id:E(y[4].name)},y[4].name),l.a.createElement("p",null,"In programming, it is easy to build code with tight dependencies and a mix of concerns that lead to solutions that are hard to cover with test and debug. ",l.a.createElement("strong",null,"Functional programming")," helps you avoid that."),l.a.createElement("p",null,"Commonly you would load a module in your function or class to implement your functionality. ",l.a.createElement("strong",null,"Inversion of control")," turns that around so that your functions are designed to be executed in other modules. ",l.a.createElement("strong",null,"Dependency injection")," is a type of inversion of control. Dependency is an external code that your function is dependent on, and injection is the act of providing it to your function."),l.a.createElement("p",null,"An example of a class ",l.a.createElement("strong",null,"without dependency injection")," would be:"),l.a.createElement(u.a,{language:"javascript",code:"import Database from 'database-stuff';\n\nclass YourClass {\n  constructor () {\n     this.database = new Database();\n  }\n  yourFunction () {\n    this.database.query();\n  }\n}"}),l.a.createElement("p",null,"Notice that database object instance is created withing the ",l.a.createElement("code",null,"constructor"),". The version ",l.a.createElement("strong",null,"with dependency injection")," would look like this:"),l.a.createElement(u.a,{language:"javascript",code:"class MyClass {\n  constructor (database) {\n    this.database = database;\n  }\n  myFunction () {\n    return this.database.query();\n  }\n}"}),l.a.createElement("p",null,"In this example, no database module is imported and no database instance is created. Instead ",l.a.createElement("code",null,"MyClass")," expects you to pass the database instance as a ",l.a.createElement("code",null,"constructor")," argument.  This approach makes ",l.a.createElement("strong",null,"managing dependencies as well as testing much easier"),"."),l.a.createElement("p",null,"In ",l.a.createElement("strong",null,"functional programming"),", this is solved by the use of ",l.a.createElement(g.a,{target:d.b.LambdaBasics},"pure functions"),". Pure function is a function that depends only on its input without any side effects:"),l.a.createElement(u.a,{language:"javascript",code:"let sideEffect = 1;\n\n// impure example dependent on sideEffect\nconst impure = () => sideEffect + 1;\n\n// pure example without any dependencies\nconst pure = input => input + 1;"}),l.a.createElement("p",null,l.a.createElement(g.a,{target:d.b.Testing},"Read more about testing in JavaScript with function programming.")),l.a.createElement("h3",{id:E(y[5].name)},y[5].name),l.a.createElement("p",null,"There are many stories of developers that have discovered functional programming and now they would never go back. Functional programming is fun because it allows you to focus on creating clever and elegant code that is easy to reason about."),l.a.createElement(h.a,null))))),l.a.createElement(c.a,null),n&&l.a.createElement(m.a,{scrolled:n,setScrolled:a}))}}}]);