There are multiple ways to define a function in elixir, before doing that let me describe what a function does.
Functions are the backbone of elixir, what they do is get input data, transform it, and output new data. Ideally each function should do one transformation only (Single Responsibility Principle).
These have to be defined inside a module like:
Note: In elixir you don’t have to write a return statement, the value of the last expression in a function is the returned value.(if no value is returned then functions return ‘nil’ by default)
Quiz: Why did we get an ArgumentError?
How to define a named function in one line:
Notice: the coma and the semicolon.
These are really easy to define:
In the first function, “a” and “b” are the input values and the output is the result of a + b
The second function is equivalent to the ‘hello’ function above.
The third function is the same as the first, but I believe the first one looks more clear with the parentheses.
We can assign anonymous functions to variables, and call them with the variable name. Let’s do that with the second function.
So all we had to do was:
The first time we try to call “helloanon” we get the same value:
#Function<20.128620087/0 in :erl_eval.expr/5>,
that we got when we declared and assigned the variable.
This happens because “helloanon” is not a function, is a variable that references the anonymous function. So we can not call “helloanon” as we did with ‘Cache.hello’ function previously.
In other languages it would make sense to call: helloanon(), right?
But that doesn’t work either, we have to call it with a dot + parentheses: .()
The reason for this is because in elixir we have a namespace for variables and a different namespace for functions. So you can have a variable and a function with the same name! And what happens if we have a variable pointing to a function and a function with the same name you may ask, well that’s what the .() notation is there for:
To differentiate calling a named function from a referenced function(anonymous).
Unlike named functions, anonymous functions are scoped from the context from which we created them. (This means we can use environment and variable values from the moment when we created the anonymous function). In a sense named functions are isolated from their calling environment.(We have to give them all context as parameter values)
To illustrate this better consider the following module:
and watch this:
As you can see even when we change the value of ‘a’ the anonymous function sticks to the value ‘a’ had when we created it.
So in both type of functions you can pass parameters but only on anonymous ones we can use context variables without having to pass them.
Now these two functions are not equivalent since, the ‘Calculator.duplicate’ has 1 argument and ‘duplicate’ doesn’t have any. The point wasn’t to make them equivalent, the point was to illustrate how environment variables affect anonymous function if we use them.
If you’re not using environment values an anonymous function will act as a named one if they have the same parameters, body, etc.
The next post is on a very important property of elixir functions: Arity