After a long time learning and working with object-oriented programming, I took a step back to think about system complexity. " — John Outerhout “Complexity is anything that makes software hard to understand or to modify. Doing some research, I found functional programming concepts like immutability and pure function. Those concepts are big advantages to build side-effect-free functions, so it is easier to maintain systems — with some other . benefits In this post, I will tell you more about functional programming, and some important concepts, with a lot of code examples. In Javascript! What is functional programming? Functional programming is a programming paradigm — a style of building the structure and elements of computer programs — that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data — Wikipedia Pure functions “water drop” by on Mohan Murugesan Unsplash The first fundamental concept we learn when we want to understand functional programming is . But what does that really mean? What makes a function pure? pure functions So how do we know if a function is or not? Here is a very strict definition of purity: pure It returns the same result if given the same arguments (it is also referred as ) deterministic It does not cause any observable side effects It returns the same result if given the same arguments Imagine we want to implement a function that calculates the area of a circle. An impure function would receive as the parameter, and then calculate : radius radius * radius * PI Why is this an impure function? Simply because it uses a global object that was not passed as a parameter to the function. Now imagine some mathematicians argue that the value is actually and change the value of the global object. PI [42](https://en.wikipedia.org/wiki/Phrases_from_The_Hitchhiker%27s_Guide_to_the_Galaxy#Answer_to_the_Ultimate_Question_of_Life,_the_Universe,_and_Everything_%2842%29) Our impure function will now result in = . For the same parameter ( ), we have a different result. Let's fix it! 10 * 10 * 42 4200 radius = 10 TA-DA 🎉! Now we’ll always pass the value as a parameter to the function. So now we are just accessing parameters passed to the function. No . PI external object For the parameters & , we will always have the same the result: radius = 10 PI = 3.14 314.0 For the parameters & , we will always have the same the result: radius = 10 PI = 42 4200 Reading Files If our function reads external files, it’s not a pure function — the file’s contents can change. Random number generation Any function that relies on a random number generator cannot be pure. It does not cause any observable side effects Examples of observable side effects include modifying a global object or a parameter passed by reference. Now we want to implement a function to receive an integer value and return the value increased by 1. We have the value. Our impure function receives that value and re-assigns the counter with the value increased by 1. counter : mutability is discouraged in functional programming. Observation We are modifying the global object. But how would we make it ? Just return the value increased by 1. Simple as that. pure See that our pure function returns 2, but the value is still the same. The function returns the incremented value without altering the value of the variable. increaseCounter counter If we follow these two simple rules, it gets easier to understand our programs. Now every function is isolated and unable to impact other parts of our system. Pure functions are stable, consistent, and predictable. Given the same parameters, pure functions will always return the same result. We don’t need to think of situations when the same parameter has different results — because it will never happen. Pure functions benefits The code’s definitely easier to test. We don’t need to mock anything. So we can unit test pure functions with different contexts: Given a parameter → expect the function to return value A B Given a parameter → expect the function to return value C D A simple example would be a function to receive a collection of numbers and expect it to increment each element of this collection. We receive the array, use incrementing each number, and return a new list of incremented numbers. numbers map For the , the expected would be . input [1, 2, 3, 4, 5] output [2, 3, 4, 5, 6] Immutability Unchanging over time or unable to be changed. “Change neon light signage” by on Ross Findon Unsplash When data is immutable, its If you want to change an immutable object, you can’t. Instead, state cannot change after it’s created. you create a new object with the new value. In Javascript we commonly use the loop. This next statement has some mutable variables. for for For each iteration, we are changing the and the . But how do we handle mutability in iteration? Recursion! i sumOfValue state So here we have the function that receives a vector of numerical values. The function calls itself until we get the list empty ( ). For each "iteration" we will add the value to the accumulator. sum our recursion [base case](https://en.wikipedia.org/wiki/Recursion_%28computer_science%29#Recursive_functions_and_algorithms) total With recursion, we keep our immutable. The and the variables are not changed. It keeps the same value. variables list accumulator : Yes! We can use to implement this function. We will cover this in the topic. Observation reduce Higher Order Functions It is also very common to build up the final of an object. Imagine we have a string, and we want to transform this string into a . state url slug In OOP in Ruby, we would create a class, let’s say, . And this class will have a method to transform the string input into a . UrlSlugify slugify! url slug Beautiful! It’s implemented! Here we have imperative programming saying exactly what we want to do in each process — first lower case, then remove useless white spaces and, finally, replace remaining white spaces with hyphens. slugify But we are mutating the input state in this process. We can handle this mutation by doing function composition, or function chaining. In other words, the result of a function will be used as an input for the next function, without modifying the original input string. Here we have: : converts the string to all lower case toLowerCase : removes whitespace from both ends of a string trim and : replaces all instances of match with replacement in a given string split join We combine all these 4 functions and we can our string. "slugify" Referential transparency “person holding eyeglasses” by on Josh Calabrese Unsplash Let’s implement a : square function This pure function will always have the same output, given the same input. Passing as a parameter of the will always returns 4. So now we can replace the with 4. That's it! Our function is . 2 square function square(2) referentially transparent Basically, if a function consistently yields the same result for the same input, it is referentially transparent. pure functions + immutable data = referential transparency With this concept, a cool thing we can do is to memoize the function. Imagine we have this function: And we call it with these parameters: The equals . This function will always result in . So we can do this: sum(5, 8) 13 13 And this expression will always result in . We can replace the entire expression with a numerical constant and it. 16 memoize Functions as first-class entities “first-class” by on Andrew Neel Unsplash The idea of functions as first-class entities is that functions are treated as values used as data. also and Functions as first-class entities can: refer to it from constants and variables pass it as a parameter to other functions return it as result from other functions The idea is to treat functions as values and pass functions like data. This way we can combine different functions to create new functions with new behavior. Imagine we have a function that sums two values and then doubles the value. Something like this: Now a function that subtracts values and the returns the double: These functions have similar logic, but the difference is the operators functions. If we can treat functions as values and pass these as arguments, we can build a function that receives the operator function and use it inside our function. Let’s build it! Done! Now we have an argument, and use it to process and . We passed the and functions to compose with the function and create a new behavior. f a b sum subtraction doubleOperator Higher-order functions When we talk about higher-order functions, we mean a function that either: takes one or more functions as arguments, or returns a function as its result The function we implemented above is a higher-order function because it takes an operator function as an argument and uses it. doubleOperator You’ve probably already heard about , , and . Let's take a look at these. filter map reduce Filter Given a collection, we want to filter by an attribute. The filter function expects a or value to determine if the element be included in the result collection. Basically, if the callback expression is , the filter function will include the element in the result collection. Otherwise, it will not. true false should or should not true A simple example is when we have a collection of integers and we want only the even numbers. Imperative approach An imperative way to do it with Javascript is to: create an empty array evenNumbers iterate over the array numbers push the even numbers to the array evenNumbers We can also use the higher order function to receive the function, and return a list of even numbers: filter even One interesting problem I solved on Path was the . The problem idea is to filter a given array of integers and output only those values that are less than a specified value . Hacker Rank FP Filter Array problem X An imperative Javascript solution to this problem is something like: We say exactly what our function needs to do — iterate over the collection, compare the collection current item with , and push this element to the if it pass the condition. x resultArray Declarative approach But we want a more declarative way to solve this problem, and using the higher order function as well. filter A declarative Javascript solution would be something like this: Using in the function seems a bit strange in the first place, but is easy to understand. this smaller will be the second parameter in the function. In this case, (the ) is represented by . That's it. this filter 3 x this We can also do this with maps. Imagine we have a map of people with their and . name age And we want to filter only people over a specified value of age, in this example people who are more than 21 years old. Summary of code: we have a list of people (with and ). name age we have a function . In this case, for each person in people array, we want to access the and see if it is older than 21. olderThan21 age we filter all people based on this function. Map The idea of map is to transform a collection. The method transforms a collection by applying a function to all of its elements and building a new collection from the returned values. map Let’s get the same collection above. We don't want to filter by “over age” now. We just want a list of strings, something like . So the final string might be where and are attributes from each element in the collection. people TK is 26 years old :name is :age years old :name :age people In a imperative Javascript way, it would be: In a declarative Javascript way, it would be: The whole idea is to transform a given array into a new array. Another interesting Hacker Rank problem was the . We just want to update the values of a given array with their absolute values. update list problem For example, the input needs the output to be . The absolute value of is . [1, 2, 3, -4, 5] [1, 2, 3, 4, 5] -4 4 A simple solution would be an in-place update for each collection value. We use the function to transform the value into its absolute value, and do the in-place update. Math.abs This is a functional way to implement this solution. not First, we learned about immutability. We know how immutability is important to make our functions more consistent and predictable. The idea is to build a new collection with all absolute values. Second, why not use here to "transform" all data? map My first idea was to test the function to handle only one value. Math.abs We want to transform each value into a positive value (the absolute value). Now that we know how to do for one value, we can use this function to pass as an argument to the function. Do you remember that a can receive a function as an argument and use it? Yes, map can do it! absolute map higher order function Wow. So beautiful! 😍 Reduce The idea of reduce is to receive a function and a collection, and return a value created by combining the items. A common example people talk about is to get the total amount of an order. Imagine you were at a shopping website. You’ve added , , , and to your shopping cart (order). Now we want to calculate the total amount of the shopping cart. Product 1 Product 2 Product 3 Product 4 In imperative way, we would iterate the order list and sum each product amount to the total amount. Using , we can build a function to handle the and pass it as an argument to the function. reduce amount sum reduce Here we have , the function that receives the current , and the object to them. shoppingCart sumAmount currentTotalAmount order sum The function is used to the by using the and starting from . getTotalAmount reduce shoppingCart sumAmount 0 Another way to get the total amount is to compose and . What do I mean by that? We can use to transform the into a collection of values, and then just use the function with function. map reduce map shoppingCart amount reduce sumAmount The receives the product object and returns only the value. So what we have here is . And then the combines all items by adding up. Beautiful! getAmount amount [10, 30, 20, 60] reduce We took a look at how each higher order function works. I want to show you an example of how we can compose all three functions in a simple example. Talking about , imagine we have this list of products in our order: shopping cart We want the total amount of all books in our shopping cart. Simple as that. The algorithm? by book type filter transform the shopping cart into a collection of amount using map combine all items by adding them up with reduce Done! 🎉 Resources I’ve organised some resources I read and studied. I’m sharing the ones that I found really interesting. For more resources, visit my . Functional Programming Github repository EcmaScript 6 course by Wes Bos JavaScript by OneMonth Ruby specific resources Javascript specific resources Clojure specific resources Intros Learning FP in JS Intro do FP with Python Overview of FP A quick intro to functional JS What is FP? Functional Programming Jargon Pure functions What is a pure function? Pure Functional Programming 1 Pure Functional Programming 2 Immutable data Immutable DS for functional programming Why shared mutable state is the root of all evil Higher-order functions Eloquent JS: Higher Order Functions Fun fun function Filter Fun fun function Map Fun fun function Basic Reduce Fun fun function Advanced Reduce Clojure Higher Order Functions Purely Function Filter Purely Functional Map Purely Functional Reduce Declarative Programming Declarative Programming vs Imperative That’s it! Hey people, I hope you had fun reading this post, and I hope you learned a lot here! This was my attempt to share what I’m learning. from this article. Here is the repository with all codes Come learn with me. I’m sharing resources and my code in this . Learning Functional Programming repository I also wrote an FP post but using mainly Clojure ❤. I hope you saw something useful to you here. And see you next time! :) My & . ☺ Twitter Github TK.