Functional, concurrent, fault-tolerant. Built on the Erlang VM. Phoenix framework for web apps.
IO.puts "Hello, World!"
name = "Mayank"
age = 15
IO.puts "#{name} is #{age}"
# Run: elixir hello.exs
# Or: iex (interactive shell)
Atoms (:ok), tuples {1,2}, lists [1,2], maps %{a: 1}. Pattern matching everywhere.
# Atoms (named constants)
status = :ok
direction = :north
# Tuples
point = {3, 4}
{:ok, data} = {:ok, "hello"}
IO.puts(data)
# Lists (linked)
languages = ["Elixir", "Erlang", "Ruby"]
[head | tail] = languages
IO.puts(head) # Elixir
IO.puts(length(tail)) # 2
# Maps
person = %{name: "Mayank", age: 15}
IO.puts(person.name)
updated = Map.put(person, :email, "test@test.com")
IO.inspect(updated)
# Keyword lists
opts = [width: 100, height: 50]
IO.inspect(opts)
# Pattern matching
def describe(x) when is_number(x) and x > 0, do: "positive number: #{x}"
def describe(x) when is_number(x) and x < 0, do: "negative number: #{x}"
def describe(x) when is_number(x), do: "zero"
def describe(s) when is_binary(s), do: "string: #{s}"
def describe(_), do: "unknown"
IO.puts(describe(42))
IO.puts(describe(-5))
IO.puts(describe(0))
IO.puts(describe("hi"))
# Case
result = {:ok, 42}
case result do
{:ok, value} -> IO.puts("Got: #{value}")
{:error, msg} -> IO.puts("Error: #{msg}")
end
# Pipe operator
"hello world" |> String.upcase() |> String.split() |> IO.inspect()
def/defp, defmodule. Anonymous functions with fn. Closures capture variables.
defmodule Math do
def add(a, b), do: a + b
defp secret(x), do: x * 2
def factorial(0), do: 1
def factorial(n) when n > 0, do: n * factorial(n - 1)
end
IO.puts(Math.add(3, 4))
IO.puts(Math.factorial(5))
# Anonymous functions
double = fn x -> x * 2 end
square = &(&1 * &1) # shorthand
IO.puts(double.(5))
IO.puts(square.(4))
# Closures
defmodule Counter do
def start(initial \ 0) do
Agent.start_link(fn -> initial end, name: __MODULE__)
end
def increment do
Agent.update(__MODULE__, &(&1 + 1))
end
def get do
Agent.get(__MODULE__, & &1)
end
end
100+ functions on collections. map, filter, reduce, sort, group_by. Stream for lazy.
nums = [5, 3, 1, 4, 2]
IO.inspect(Enum.sort(nums))
IO.inspect(Enum.reverse(nums))
IO.inspect(Enum.map(nums, &(&1 * 2)))
IO.inspect(Enum.filter(nums, &(&1 > 2)))
IO.inspect(Enum.reduce(nums, 0, &+/2))
IO.inspect(Enum.min(nums))
IO.inspect(Enum.max(nums))
# Chaining
result = nums
|> Enum.filter(&(&1 > 2))
|> Enum.map(&(&1 * 10))
|> Enum.sort()
IO.inspect(result) # [30, 40, 50]
# Group by
people = [
%{name: "Alice", age: 20},
%{name: "Bob", age: 12},
%{name: "Charlie", age: 25},
]
grouped = Enum.group_by(people, fn p -> if p.age >= 18, do: :adult, else: :child end)
IO.inspect(grouped)
# Stream (lazy)
Stream.map(1..1_000_000, &(&1 * 2)) |> Enum.take(5) |> IO.inspect()
spawn, send, receive. Processes don't share memory. Message passing is the only way.
# Spawning a process
pid = spawn(fn ->
receive do
{:hello, sender} -> send(sender, :world)
end
end)
send(pid, {:hello, self()})
receive do
:world -> IO.puts("Got response!")
end
# Agent (stateful process)
{:ok, agent} = Agent.start_link(fn -> [] end)
Agent.update(agent, fn state -> [1 | state] end)
Agent.update(agent, fn state -> [2 | state] end)
IO.inspect(Agent.get(agent, & &1)) # [2, 1]
Agent.stop(agent)
# GenServer
defmodule Counter do
use GenServer
def init(_), do: {:ok, 0}
def handle_call(:get, _from, state), do: {:reply, state, state}
def handle_cast(:inc, state), do: {:noreply, state + 1}
end
{:ok, pid} = Counter.start_link()
GenServer.cast(pid, :inc)
IO.puts(GenServer.call(pid, :get)) # 1
# mix phx.new my_app
# cd my_app && mix ecto.create && mix phx.server
# router.ex
scope "/", MyAppWeb do
pipe_through :browser
get "/", PageController, :index
resources "/users", UserController
end
# LiveView โ real-time without JS
defmodule MyAppWeb.CounterLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
{:ok, assign(socket, count: 0)}
end
def render(assigns) do
~H"""
<h1>Count: <%= @count %></h1>
<button phx-click="inc">+1</button>
"""
end
def handle_event("inc", _params, socket) do
{:noreply, update(socket, :count, &(&1 + 1))}
end
end