Elixir: Anonymous Functions, Modules, and More

5 minElixir

Elixir is a dynamic, general-purpose, functional programming language. It was created by José Valim, a developer with a background in Ruby, with the specific intent to utilize the scalability and maintainability features of the Erlang platform. Although not the most popular language out there, Elixir is beloved by its users. Companies such as Spotify, Discord, and Heroku have already adopted Elixir for its ease in building distributed, concurrent, and fault-tolerant systems.

Anonymous Functions, Modules, and More

Elixir also supports anonymous functions, which can be defined using the fn keyword or with the shorthand & syntax.

sum = fn a, b -> a + b end
IO.puts sum.(1, 2)

# 3
elixir
sum = &(&1 + &2)
IO.puts sum.(2,3)

# 5
elixir

Modules

Modules are used to organise named and private functions into a namespace. Here are some examples with public and private functions.

defmodule CoolStuff do
  def calculate(num1, num2) do
    IO.puts num1 + num2
  end
end

CoolStuff.calculate(1, 2)

defmodule Greet do
  def hello(name) do
    greeting(name)
  end

  defp greeting(name) do
    IO.puts "Hello" <> " " <> name
  end
end

Greet.hello("John")
elixir

Module Attributes

Used as constants throughout the module.

defmodule Greetings do
  @name "George"

  def hello(), do: "Hello #{@name}"
  def morning(), do: "Good Morning #{@name}"
  def night(), do: "Good night #{@name}"
end

Greetings.hello()
elixir

Module Documentation

Documentation can be attached to modules and functions.

defmodule Example do
  @moduledoc"""
  This is my module documentation
  """

  @doc"""
  This is my test function
  multiline comment and documentation.
  """

  def test() do
    "this is a test"
  end

  # This is a line comment
  def test2(), do: "nothing"
end
elixir

Structs

In Elixir, a struct is a data structure that provides an alternative to using maps or tuples for storing and manipulating related data.

defmodule User do
  defstruct [:name, :age]
end

u = %User{age: 20}
u.age
elixir

Alias

An alias is a way to create a shorthand for a module or a module's function.

defmodule AnotherModule do
  def another_function do
    IO.puts "Hello"
  end
end

defmodule MyModule do
  alias AnotherModule, as: Another

  def my_function do
    Another.another_function()
  end
end

MyModule.my_function()
elixir

Import

Import allows us to use functions from other modules directly.

defmodule ImportExample do
  import Math

  def import_sum(num1, num2) do
    sum(num1, num2)
  end
end

ImportExample.import_sum(1, 2)
elixir

We can use only to import specific functions, or except to exclude specific functions.

Function Arguments

Functions in Elixir can have default values for arguments.

defmodule Say do
  def hello(name, last_name, _greeting \ "Hello!") do
    "#{_greeting}! #{name} #{last_name}"
  end
end

Say.hello("John", "Barton")
elixir

Function Pattern Matching

Pattern matching is a key feature of Elixir.

defmodule Alphabet do
  def letter(:a), do: "a"
  def letter(:b), do: "b"
  def letter(:c), do: "c"
  def letter(letter), do: letter
end

Alphabet.letter(:a)
Alphabet.letter("other")
elixir

Useful modules and built in functions

Elixir comes with a range of built-in modules and functions.

Integer.to_string(1)
String.capitalize("a")
String.contains?("This is a string", "This")

fruits = ["banana", "apple", "orange"]

List.last(fruits)
List.to_string ["a", "b", "c"]

letters = %{"a" => "A", "b" => "B"}
Map.put(letters, "c", "C")

Enum.each(fruits, fn x -> IO.puts x end)

length fruits
to_string 1
elixir

Pipe Operator

The pipe operator, represented as |>, is a fundamental feature in the Elixir programming language. It is used for chaining functions together in a readable manner. The purpose of the pipe operator is to enhance code readability and enable a more fluent style of programming. When using the pipe operator, the result of the expression on the left is automatically inserted as the first argument of the function on the right.

string = " My String "

string
|> String.downcase()
|> String.trim()
|> String.split()
|> Enum.join("-")

IO.puts string

# "my-string"
elixir