2.2 Modules and Functions
In this lesson you'll learn about modules and functions. These are how code is organized in Elixir. Functions, of course, are the most important feature of a functional programming language.
1.Introduction3 lessons, 11:49
2.The Elixir Language5 lessons, 30:55
3.Concurrency in Elixir6 lessons, 35:27
4.Conclusion1 lesson, 01:35
2.2 Modules and Functions
Hi, and welcome back to get started with Elixir. In this lesson, we are going to talk about modules and functions. We already talked about anonymous functions that are bound to a variable. It is important to note that you have to use a dot between the value that stores the function and the arguments since the function itself has no name. In the what is functional programming lesson, I already used the syntax for named functions. They are defined by the def keyword and receive a name and some parameters in parentheses, followed by a do and block. It is important to know that named functions can only be defined inside a module, they're used to organize your code. You can create one by using def module. Another important thing is that the functions always return the result of the last statement in them. There is no need to use a return keyword. In fact, there isn't even one in the syntax. Here we defined a simple math module, which has an add method in it, that adds two values together. If you want to use a function in the module, you have to use the module name and the function name. In our case, math.add, and then the parenthesis. If you are inside another function in the same module, you can omit that module name. You can also define private functions that can only be called within the module. You have to use defp instead of just def. Sometimes you want to call a function that is in another module, which is nested inside other modules. Nesting is also a possibility when defining modules. You have two possibilities to make your life easier here. Either you alias a module, so you can call it by using only the last module name, or even by defining a special name just inside your module for it. Or you can import it, which lets you use the functions as if they were defined in your module. If you don't want to import everything, you can only import certain functions as the only option. They key is the name of the function, and the value is the number of parameters of this function. We haven't talked about it yet, but functions are generally referenced by the name and the number of parameters. You will see this very often in Arab messages. The function truthy that has no parameters is referenced as truthy/0. The sum function we defined earlier would be sum/2. When we talk about modules and functions, we have to also talk about module attributes. They used to annotate your modules and functions. This is also the way documentation is written, which Elixir values very highly. To document the module, you can use the add module.annotation. You should do this right underneath the module's definitions with the travel quote syntax, you can also use mark.syntax here. To document the function, you can use add doc accordingly, the only exceptions are product functions. You can't use this annotation on them. Finally, you can use a module of the defstruct keyword to define a struct of the same name and provide default values for it that get used when no value for defined key is provided. Let's try it out. First, let's create a new file called course.exs. With Elixir, you have two different file types. .dx files need to be compiled beforehand, and .exs files, which stands for Elixir script, get interpreted on the fly. I'm going to define a course module, and within it a struct of the attribute's name and author. The name by default is nil, and the author defaults to my name. Let's also define a function called author_firstname that will return the first name of the author. It takes a course as the only parameter. To implement this, I'm going to introduce another concept to you, it is the pipeline operator. This can be used to pass on a value through a set of functions as the first parameter of those functions. In our case, we will take the author.name and pass it to string.split. Split uses spaces by default, so we don't need parameters here. Then we pass the resulting list of the operation to list.first to get the first element. To run our example, we can use iex by passing the file name to it. Let's create a course called Get Started With Elixir, let's now authenticate. Notice that it automatically used the default for the authenticate. Let's try searching the authors first name by calling the function, and it just returns markers. Great. I'm going to go back to the file and be a good citizen. I will document the code. Well, the module defines a course struct and functions to work with courses. The author first name function returns the first name of the course's author. It is also common courtesy to provide a description of the parameters. In our case, just the course and an example section. Here we can provide an example on how to use the function and the expected return values. To recap, modules are used to organize your code and are required when using named functions. You can define functions with def, and private functions with defp. Using other modules is often combined with an alias or import statement. You can define structs like the module with defstruct and provide defaults for it. In the next lesson, we are going to learn how to control the flow of your functions and how to use recursion. See you there.