The Art of

 

Kasun Vithanage

What is Elixir

  • It's a functional language
  • Concurrent
  • Fault-tolerance
  • Distributed
  • Extensible

Who uses Elixir

Let's Get Started

  • You can use Livebook
    • Its like Jupyter for Python
  • You can use IEX for REPL
    (with Elixir installation)

Basic Types

Run in Livebook

Key takes

  • Elixir uses `snake_case` for variables
  • There are lot of data types you need to explore
  • Remember that some operators had `/` followed by a number? well keep that in mind...its called arity

Lists and Tuples

Run in Livebook

(Linked) Lists

  • Implemented as Linked Lists
  • Stored as non contiguous
  • Appending is Slow, Prepending is fast
  • Can store any type of data
  • Calculating length is slow

Tuples

  • Stored as a contiguous structure
  • Accessing any index is really fast
  • Updating a tuple is expensive
  • Can store any values
  • If you want to return multiple values
    from a function, tuple is the way to go

What the heck is Immutability?

// JavaScript - Mutable array example
function addNumbers(numbers) {
    numbers.push(4);         // adds to end
    numbers[0] = 99;        // changes first element
    numbers.sort();         // sorts in place
    return numbers;
}

const numbers = [1, 2, 3];

console.log('Before:', numbers);
// Before: [1, 2, 3]

addNumbers(numbers);
console.log('After:', numbers);
// After: [2, 3, 4, 99]

// Original array was mutated!
console.log('Original array changed:', numbers);

As you can see original data is changed

If we refer this again it may lead to errors

This is common for objects as well

Problem of immutability exists in OOP based languages like Java, C# etc

We had a bug in AB due to mutability

Solution was to just not mutate original arrays

They are super hard to track 😒

Functional programming removes mutability

Which eliminates a whole class of bugs by design

Maps
and
Keyword Lists

Run in Livebook

Maps

  • Maps are simply HashMaps
    • In JS you call this an object
    • In python this is called a dictionary
  • Its mostly the "go to" data structure in FP
  • Maps keys are unordered
  • Keys and Values can be just anything you want

Keyword Lists

  • They are just lists with few special properties
    • Keys must be atoms
    • Keys are ordered, as specified by developer
    • Keys can appear more than once
  • Often used for passing optional arguments to functions

Pattern Matching

Run in Livebook

💡New Concept

  • = is match operator
  • use pin (^) to match with existing values
  • Heart of Functional Programming
    is Pattern Matching
  • It allows you to write code without thinking about the underlying data in an imperative way
  • Your code will be much more readable

Functions

and

Modules

Run in Livebook

Modules

  • You can group functions nicely
  • We previously encountered several modules
    • Map
    • Keyword
    • List
    • File
  • They are not classes !!!
  • Module names are in PascalCase
    • MyApp.Billing
    • MyApp.WebHooks.Stripe
  • These names are not bound to any file, so you
    can even create Foo.Bar.A.B.C as a module name

Control Flow

Run in Livebook
  • In elixir every statement returns a value
  • So we dont have early returns(no return keyword)
  • Instead focus on breaking logic into smaller
    functions
  • use pattern matching on function heads with guards
  • use if/unless, case, cond, with to control the flow
    often paring with other concepts
  • In elixir its common to pattern match on function heads, this is also a control flow
  • Pattern matching is the key for everything

Pipes |>

Run in Livebook
  • Pipes allows you to write less codes
  • Often you can see the flow of data when
    using pipes making code much more clear
  • Its common to use pipe for operations
    involving enums or streams

Structs

Run in Livebook
  • They are super powered maps
  • Allows us to do compile time checks
  • Data validation
  • Structure code well

Looping

We dont have loops

Because we cant mutate

Run in Livebook
  • Loops often have a variable for condition
  • Some loops involves mutating a counter
  • We cant do that in elixir
  • So how we do it in FP then?
for (let i = 0; i < 5; i++) { // we cant do i++ in Elixir
    console.log(i);
}

Recursion with Meeseeks

  • Recursion
    • Its a powerful tool
    • With Pattern matching it becomes natural
    • Tail recursion acts like a for loop
  • Enum.each like functions
  • List comprehensions
    • Looks like for loops, but they arent
    • Really handy to generate stuff

Error Handling

Run in Livebook
  • In Elixir often we use tuples to represent
    results, and use pattern match on them
  • In rare cases we can opt into try/catch/rescue
    • Its very uncommon 🤯
  • If a function raise an exception, we use ! 
    • Like File.read!/1

Important
Notes

  • Data Structures are immutable, if you want to update
    replace entire thing at once
  • Pattern Matching is the Key
  • Think in terms of functions and composing
    functions(like composing react components)
  • Break your logic
  • Some conventions
    • odd? - the ? denotes that function returns
      a boolean
    • read! - ! denotes the function may raise an
      exception

QnA

:stop 🕰️

I think we covered enough for today

Let it sink in 🛳️

Welcome Back

What about State?

If its immutable how we can hold state?

Processes

Run in Livebook
  • Elixir is built on top of BEAM VM
  • BEAM VM was developed to run Erlang
  • Erlang has a concept called `Process`
    • Not to confuse with processes in OS
  • All the code you saw running inside processes
  • Its the only base in Elixir/Erlang for concurrency
  • They are cheap in terms or Memory and CPU 💸
  • You can have thousands or more processes running
    at same time 🤩
  • You can pass messages between processes

Rise of

  • Telecom Systems need to be reliable and highly available(non-stop)
  • At that time(in the 80s) telephone switches were written using C
  • Upgrading the software of these switches was hard
    • Specially when people still calling someone all the time
  • People at Ericcson wanted to solve this problem
  • They created Erlang as the solution
Joe A

Joe Armstrong

Creator of Erlang

📖 Thesis of Erlang

The Lost OOP

 

  • It was developed considering cells in a biological
    systems 
  • Cells can communicate with other cells through
    various ways, like in human body with electrical signals
  • Even though cells are self contained, these coordinated messages can make them do complex tasks
    • Ever imagined how you can lift a weight? its
      your nervous system sending messages to muscle
      fibers
    • Ever imagined how your immune system works? 

Father of OOP

Dr Alan Kay

In orignal OOP Concept

  • There were no classes
    • So no Blueprint nonsense 😃
  • No mutability, you need to pass a message
    to an entity, the entity can decide how to process
    the message
  • Messages are processed sequentially
  • Erlang is the closest thing to this original concept
    as for today

Erlang is similar to
Actor model

But they developed it separately

Concurrency 

  • NodeJS is single threaded
    • Node has an event loop which handles
      workload
    • No multicore support
  • Java, C#, C++ are multi threaded
    • Has multi core support
  • Go, Erlang/Elixir are concurrent
    • Can be used with multicores and even single
      cores

NodeJS Event Loop

Multi Threading is superb

but...

Complexity with Threading/Concurrency

  • Shared resources
    • One of more thread can modify/access
      data without coordination leads to
      unpredictable behaviours
  • Race Conditions
  • Deadlocks and Starvation
  • Coordination becomes complicated
  • Error handling is complex

Deadlock

Race Condition

Whats the cause?

  • Mutable data structures
  • No data isolation
  • Coordination is complicated

Solutions

  • Mutexes
  • Semaphores
  • synchronized - Java
  • and others tools based on lang

Mutexes

Semphore

Erlang got you 🙌

  • Processes are isolated
    • No shared memory or state
    • No one can modify state
    • Immutable data structures
    • Functions are thread safe by default 🤩
    • So no mutexes or semaphores 
  • Message Passing
    • Mailbox process messages in arrived order
    • So no sync issues
  • Fault Tolerence
    • Crashing doesnt bring everything down
  • Efficient Scheduling
    • Lightweight processes
    • Preemptive Scheduling in BEAM

In Node, if unhandled exception was thrown, it can bring down entire system

So don't even worry

GenServer

"Generic Server"

Run in Livebook
  • GenServers allows you to hold complex State
  • Its coming from OTP(Open Telecom Platform)
  • handle_call is replying to the caller (who is waiting).
  • handle_cast is fire and forget, caller doesn't wait
  • handle_info handles any other message

Supervisors

Run in Livebook
  • Fault Tolerance is built in
  • Use Supervisors to handle issues with
    processes and take actions
  • There are other supervisors like
    DynamicSupervisor
  • Recover from errors without bringing
    everything down

"Let it Crash"

This is for unexpected errors only

Open Telecom Platform

Its not about Telecom

  • GenServer/Supervisor are a part of
    OTP platform created on top of Erlang
  • Back then Erricson developed a platform
    abstracting useful concurrency patterns under
    OTP
  • Later they made it publicly available 
  • OTP is the center of any modern Elixir app

Tooling

  • mix is your new npm
  • hex.pm is your npm.com
  • iex is your new node repl
    • Most of the time you will use iex
  • ElixirLS, Lexical are VS Code Extensions
    for code completion(Language servers)
  • mix format is your prettier
  • credo is your eslint
  • hexdocs is where you go for docs

Ecosystem

We will explore them practiaclly

  • Phoenix Framework - Your web framework
    • Its similar to Express/Nest/FastAPI
    • Supports real time connections out of the
      box. So no need of Socket.io/WebSockets
    • Highly scalable
  • Ecto - Database ORM and Query builder
    • Similar to Objection/Knex/Kysely
    • Closer to SQL 
  • Oban - Schedule jobs
    • Similar to PgBoss
  • Broadway - Build data pipelines
    • Supports RabbitMQ, SQS, Google PubSub
  • Cachex - A distributed cache
    • Similar to Redis 
  • Req - a HTTP client
    • Similar to Axios
  • Jason - a JSON library
    • Next elixir release will have built in JSON
  • ExAws - AWS for elixir
  • stripity_stripe - Stripe for Elixir
  • LiveView - A realtime way to build UIs
    • Similar to React/Vue + WS

Erlang/Elixir has a rich standard library

Thinking
in

Elixir

  • Think of the Happy path
  • Think of creating small reusable functions
  • Worry less about data mutations
  • Clear concise codes showcasing
    underlying business requirements
  • Be better programmers
    • Working with Elixir made me a better
      programmer with other langs

After you took some Elixir

It's not a silver bullet

  • Its not easy to onboard devs
  • We wont possibly hire elixir devs
    • We can hire node devs, but not elixir
    • Instead we have to train them 
  • Limited number of libraries
    • You may find that most libraries arent
      there for elixir
  • Types - Its not typesafe like Typescript
    • There is an ongoing effort to bring types
  • DX is not great
    • Ongoing effort to make ElixirLS better
  • Learning curve
    • Functional programming re-wire your
      brain

Where to get help?

Don't be afraid to ask questions

When i started, i was always asking questions from experts

QnA

The End

Leap of Faith

The Art of Elixir

By Kasun Vithanage

The Art of Elixir

To the battle

  • 338