Basics
- Mix
- Hex
- IEx
- ExUnit
- ExDoc
- Immutable data and variable rebinding
- Processes
- Dogmatic
- Influenced by ruby
$ elixir -v
Erlang/OTP 20 [erts-9.0] [source] [64-bit] ...
Elixir 1.4.5
Elixir Phoenix
[info] Sent 200 in 43ms
[info] Sent 200 in 178µs
Ruby on Rails
Completed 200 OK in 199ms
Completed 200 OK in 9ms
Mix
- mix.exs like Gemfile / Rakefile
- https://hex.pm
- https://hexdocs.pm
- mix deps.get
- mix test
- mix hex.publish
- mix compile
- rebar3
defmodule Plug.Mixfile do
use Mix.Project
@version "1.4.0-dev"
def project do
[app: :plug,
version: @version,
elixir: "~> 1.3",
deps: deps(),
package: package(),
description: "A specification and conveniences for composable " <>
"modules between web applications",
name: "Plug",
xref: [exclude: [:ranch, :cowboy, :cowboy_req, :cowboy_router]],
docs: [extras: ["README.md"], main: "readme",
source_ref: "v#{@version}",
source_url: "https://github.com/elixir-lang/plug"]]
end
# Configuration for the OTP application
def application do
[applications: [:crypto, :logger, :mime],
mod: {Plug, []},
env: [validate_header_keys_during_test: true]]
end
def deps do
[{:mime, "~> 1.0"},
{:cowboy, "~> 1.0.1 or ~> 1.1", optional: true},
{:ex_doc, "~> 0.15", only: :docs},
{:hackney, "~> 1.2.0", only: :test}]
end
defp package do
%{licenses: ["Apache 2"],
maintainers: ["José Valim"],
links: %{"GitHub" => "https://github.com/elixir-lang/plug"}}
end
end
IEx
iex(10)> h Enum.map
def map(enumerable, fun)
Returns a list where each item is the result of invoking fun on each
corresponding item of enumerable.
For maps, the function expects a key-value tuple.
## Examples
iex> Enum.map([1, 2, 3], fn(x) -> x * 2 end)
[2, 4, 6]
iex> Enum.map([a: 1, b: 2], fn({k, v}) -> {k, -v} end)
[a: -1, b: -2]
* access documentation
iex(6)> i :atom
Term
:atom
Data type
Atom
Reference modules
Atom
Implemented protocols
IEx.Info, Inspect, List.Chars, String.Chars
Help, Info and IEx.pry
ExUnit
defmodule MyApp.MyController do
@twitter_api Application.get_env(:my_app, :twitter_api)
def show(conn, %{"username" => username}) do
@twitter_api.get_username(username) #...
end
end
# In config/test.exs
config :my_app, :twitter_api, MyApp.Twitter.InMemory
# In config/prod.exs
config :my_app, :twitter_api, MyApp.Twitter.HTTPClient
defmodule MyApp.MyControllerTest do
use MyApp.ConnCase
setup do
{:ok, username: "josevalim"}
end
describe "GET /twitter", context do
test "returns the user's twitter handle" do
conn = get(context[:conn], "/twitter")
result = Poison.Parser.parse!(conn.resp_body)
assert result["username"] == context[:username]
end
end
end
Elixir Processes
for num <- 1..100000, do: spawn fn -> num * 2 end;System.halt
# 1.2 seconds
Elixir Processes
defmodule Example do
def listen do
receive do
{:ok, "hello"} -> IO.puts "World"
end
listen
end
end
iex> pid = spawn(Example, :listen, [])
#PID<0.108.0>
iex> send pid, {:ok, "hello"}
World
{:ok, "hello"}
iex> send pid, :ok
:ok
Erlang Interop
# mix.exs
defmodule Test.Mixfile do
use Mix.Project
# included for inclusion in release
def application do
[mod: {Test, []},
applications: [:phoenix, :phoenix_html, :cowboy, :logger,
:gettext, :phoenix_ecto, :phoenix_pubsub,
:mariaex, :httpoison, :eldap]]
end
end
# elsewhere, charlist instead of string
:eldap.open('kissmetrics.com', [{:port, 389}, {:ssl, false}])
Deployment
- https://github.com/bitwalker/distillery
- https://github.com/bitwalker/conform
- include ERTS
- hot upgrades
#!/bin/sh
set -e
MIX_ENV=prod mix do deps.get, compile
# refresh release config
rm -f config/app.conf
# generate sys.config for erlang
# and conf file
MIX_ENV=prod mix conform.configure
# compile assets
npm install
npm run compile
# run digest *after* npm compiles
MIX_ENV=prod mix phoenix.digest
# matching architecture
MIX_ENV=prod mix release