Started learning Elixir and i wanted to use this as sort of notes to make sure i understand the topic that i’m learning.
Elixir is a dynamically typed (just like javascript) functional programming language where the typecheck happens only at runtime.
You simply define a variable like this:
Important
Numbers aren’t always floating point numbers like in javascript
variableA = 1
variableB = 2
count = 0
# you can reassign a variable to a different type
count = false
count = "heh"
defmodule is used to define a “module” - similar to a class in OOP
def is used to define a public function
defp is used to define a private function
The value of the last expression in a function is always implicitly returned
Functions can be written in one line:
defp private_subtract(x, y), do: x - y
It is common to use PascalCase to define module names, and unlike javascript,
variable and function names should use snake_case.
Elixir has a Kernel module which is automatically imported, this includes
basic arithmetic operations.
Arity of functions
The term is used to define how many arguments a function accepts:
# add/3 because this function has three arguments, thus an arity of 3
def add(x, y, z) do
x + y + z
end
Anonymous functions
Think of anonymous function in Elixir like arrow function in javascript, example:
# you define them using the reserved keyword `fn`, `->` instead of `do`
add_one = fn num ->
num + 1
end
# then you invoke like this
add_one.(1)
# => 2
Confusingly, this function above can be rewritten like this:
add_one = &(&1 + 1)
add_one.(1)
# => 2
They call this the “capture” operator, or
&/1.
Important
Anonymous functions need to be invoked using the dot operator (
./2) before the parentheses; named functions do not.
//2 always
returns a float. Use div/2 and
rem/2 (the remainder function)
for integer division and remainders.
These functions are from the Kernel
module, as mentioned above.
Bit manipulation
Not gonna lie i’m a bit excited about this - never really had the opportunity to use bitwise operations in javascript since it’s use cases are really niche (maybe in Elixir too)
Seems to be the case - Elixir has a Bitwise module that comes with bitwise functions
Side quest
While doing the exercise from Exercism, i found community solutions which solve
the tasks using the short hand capture notation and noticed that the person uses
then(secret_function1) to pipe the value to the next function instead of
secret_function.():
add5 = secret_add(5)
10 |> add5.() # add5.(10) => 15
10 |> then(add5) # then(10, add5) => add5.(10) => 15
then/2 is from the
Kernel module and is mostly used with
the pipe operator (|>) to
inline an anonymous function, like this:
user |> then(fn u -> {u.id, u.name} end)
Or when the value from the pipe needs to be placed as a second argument:
5 |> then(&Enum.at([1, 2, 3, 4, 5, 6], &1))
Why the dot (when calling anonymous functions)?
Also i went on another rabbit hole trying to figure out why they invoke named and anonymous functions differently. This is pretty unusual coming from javascript so i decided to find the truth.
Then i stumbled upon this article which actually answers my question and to summarize in my own words, basically boils down to whether variables and functions are stored in a single namespace or different namespaces (for Elixir to know whether it’s calling an anon function stored in a variable or a named function).
Similarly in Erlang, the difference is not by using the “dot” when calling the anon function, but functions are defined with lowercase and variables start with an uppercase - so there is no way those two would clash.
If you’re interested in reading more, check out this paper
Booleans
When writing a function that returns a boolean value, it is common to use the
? suffix, similarly for variables that store boolean values:
def either_true?(a?, b?) do
a? or b?
end
Even when using the variable and calling the function, you’d still need to use
the ? suffix - if variable is defined with ?, then it needs to stay, if not,
then ? can be omitted.
&&/2,
||/2, and
!/1 operators can also be used
instead of and/2,
or/2, and
not/1, respectively.