Next lesson playing in 5 seconds

  • Overview
  • Transcript

1.2 What Is Functional Programming?

Hi and welcome back to get started with Elixir. In this lesson, I'll explain the most important functional programming concepts to you. If you have any experience in programming, forget everything you know. Well, not entirely, but almost. The concept of Functional Programming are radically different. But to make the language more practical, Elixir has watered down some of those principles. The most important concept or difference is what functions represent in Functional Programming. In the most simple sense, there are mapping of one or more inputs to some output. The most simple form is pure functions. They are purely dependent on their inputs and don't rely on external state and to the same input, always produces the same output. Let's look at a simple function, square. The square function takes the input and multiplies it by itself. Every time, as long as the input stays the same, the output does as well. If a function does something else like storing a record in a database, it produces a side effect and is no longer a pure function. If we have a look at our function from before, but this time add a log function to it, we have produced a side effect. Now there's also the concept of higher-order functions. Those also takes function as input making it more flexible and reusable. Look at this example. Besides the square function, we also have a double function that multiplies the value by 2. Now lets say we want to have two other functions, fourth to get to fourth power and quadruple. Both of these functions require their counterparts to be called twice. To reduce the fixtures overhead, I'm going to introduce another function that is called twice, which receives a function and the value, and calls the function twice. Now we can let fourth use the twice function with square and quadruple will parse double. Twice in this case is a higher order function. The next important concept is mutability. In functional programming, you can't change variables. Let's look at a simple JavaScript array. It has the values of 1, 2, and 3. When we call x.pop, the value x gets changed and only contains 1 and 2. This is not possible with functional languages. In Elixir, this concept doesn't show that clearly, because you can reuse variable names. Let's look at an example. Here I have a variable x that holds a value 2. Now I want to add 3 to the value x, which reads as x = x + 3. In Elixir this won't produce an error, since it tries to be more practical. Another important concept I wanted to show you is Pattern Matching. This is used excessively in functional programming languages and you will learn why in a minute. You have already seen the pattern matching syntax. It is the equals operator. Let's take the following example. The variable x is set to 2. If we are calling 3 = x, it will raise a match error because 2 is not 3. Of course reversing the value and the variable is not always what you want. If you want the value to be matched, you have to use the second flex operator before the variable name. The place where pattern matching really shines is function definitions. You can define a function that not only requests a given number of variables, but also a specific format. Let's say we have a function match that works differently depending on which type of inputs you have. If the first element is a list, then we are going to concatenate it. Don't worry, I'll explain the syntax in later lessons in more detail. We also have a variant of merge that doesn't care about the input and just adds the two values together. This means if I parse analyst, it will concatenate it and return the match list. If I parse in a value, it will add them together. Let's add a third variant at the bottom that requires the first argument to be 1. And in that case, just adds b plus b. If I pass 1 and 3, the output is not 9, as expected, but 4. This is because the order in which you define the functions matters. If the input arguments match with a function, it is chosen. If not, the next one will be tried. There's one final and important concept to tackle before the end this lesson and this is recursion. It is very prominent paradigm in the functional programming world. Let's have a look at the following example. A function sum that takes two list where every element gets added to its counterpart to return a new list. In the first pattern, we're going to extract the first element as a and the reminder of the list as aa. Similar, the second element is b with the reminder as bb. Within the function, the values of a and b get added together, and now it's time for recursion. We have to call the sum again and parse the remainders. The result will be concatenated to the result of the addition. This works until we hit the end of the list and we have no more tail. The pattern won't match anymore, therefore we need a terminator. In our case we are going to match the first argument to be an empty list and use an underscore as the second. This tells the function that we don't care about the value and won't use it. In this function, we return just an empty list which doesn't have any effect on the return value. Of course in this example, the first list needs to be longer than the second one. Otherwise it will fail. As an exercise, you could add more exhaustive variants to also cover these cases. To recap, functional programming is all about functions, there are no classes. Pure functions only use the input to produce an output and don't rely on an external state. Higher-order functions take other functions as arguments to define their behavior. Variables are immutable and can only be reassigned, not altered. Pattern matching allows us to create functions that perform different code, depending on the input. Recursion is one of the core concepts of functional programming, and it's often used instead of loops. In the next lesson, we're going to install Elixir and try out the Elixir REPL IEX. See you there.

Back to the top