INTRODUCTION TO ELIXIR
Madrid |> Elixir29/03/2016
Offered by
RUBY ON RAILS SHOP EMBRACING ELIXIR
About me:Javier Cuevas@javier_dev
P2P MARKETPLACE FOR DOG OWNERS
About
JavierCuevas
VictorViruete
RicardoGarcia
BrunoBayón
Artur Chruszc
WHAT IS ELIXIR?
Elixir is a dynamic, functional language designed for building scalable and maintainable applications.
Elixir leverages the Erlang VM, known for running low-latency, distributed and fault-tolerant systems.
Created by José Valim circa 2012.Former Rails Core Team member.
He was trying to make Rails really thread safe but... ended up creating a new programming language. Ops!
Elixir:
• Compiles to Erlang bytecode.
• It is not Ruby compiling to Erlang.
• Can call to any Erlang library with no performance penalty.
• Enables developers’ productivity by offering amazing tooling and beautiful documentation.
• WhatsApp• Facebook (Chat backend)• Amazon (SimpleDB)• AdRoll• Heroku
• Yahoo (Delicious)• Ericsson (mobile networks)• T-Mobile (SMS)• World of Warcra!• ....
Erlang is that ugly language from 1996 used in production by some “small” guys such as:
2 million connections in a single node
WHY SHOULD I CARE ABOUT
ELIXIR?
• CPUs today have gazillion of transistors (more than ever), and a lot of cores.
• There is no way we can keep them busy by trying to get them do all something at once.
• The only way to keep them busy is diving the work.
• In other words: The future is functional and concurrent.
• Elixir proves that functional programming does not need to be mathematical or complex.
• With Elixir we can do concurrency programming without having to use abstractions such as locks or semaphores.
How do we program without GOTO state?– Computer Science, 1968
How do we program without mutable state?– Computer Science, 2016
SHOW ME THAT
ELIXIR
Value Types
• Integers (arbitrary precision)
• Floats0.12346
• Atoms (aka symbols):my_atomtrue, false and nil are atoms
• Rangesstart..endstart & end can by any type
• Regular expresions~r{regexp}
Collection Types• Tuples (not arrays)
{:ok, 42, "next"}
• Linked Lists(closest to arrays)list = [1,2,3,4]hd(list) # 1tl(list) # [2, 3, 4]
• Binaries<<1,2>>Strings are UTF-8 encoded binaries.
• Maps%{ key => value, key => value }
countries = %{"ES" => "Spain", "Fr" => "France"}countries["ES"] # Spain
System Types
• PIDs:Reference to local or remote process.A new PID is created when you spawn a new process
• Ports:Reference to a port ^_^
Anonymous Functions
• AKA unnamed functions.
• Can be passed as arguments (they’re also a type)
• Parenthesis are optional.
iex> add = fn (a, b) -> a + b end#Function<12.71889879/2 in :erl_eval.expr/5>
iex> add.(1, 2)3 that dot before parenthesis is only for calling anonymous functions
Named Functionsdefmodule MyModule dodef say_hello(name) doIO.puts “Hello #{name}”
endend
iex> MyModule.say_hello("Madrid Elixir")Hello Madrid Elixir
Pattern Matching• In Elixir: a = 1
does not mean we are assigning 1 to the variable a.
• The equal signs means we are asserting that the le! hand side (LHS) is equal to the right one (RHS). It’s like basic algebra.
iex> a = 11iex> 1 = a1
you can’t do that in non functional languages
Pattern Matching
• Instead of assigning a variable, in Elixir we talk about binding a variable.
• In contrasts to Erlang, Elixir does allow rebinding a variable.
iex> a = 11iex> a = 22
Pattern Matching
Let’s do some magic:iex> [1, a, 3] = [1, 2, 3] [1, 2, 3]
iex> a2
Pattern Matching
You can ignore values with “_”iex> [a, _, _] = [1, 2, 3][1, 2, 3]iex> a1
Pattern Matching
You can reuse the previous bind value with the pin operator “^”
iex> a = 11iex> [^a, 2, 3 ] = [ 1, 2, 3 ][1, 2, 3]
Pattern Matching & Function Signatures
Function signatures use pattern matching. Therefore we can have more than one signature.
defmodule Factorial do def of(0), do: 1 def of(x), do: x * of(x-1) end
look mum! programing without if - else
GuardsWhen pattern matching is not sufficient to select the signature to use, we can use guards.
defmodule Factorial do def of(0), do: 1 def of(n) when n > 0 do n * of(n-1) endend
Guardsdefmodule MyModule do def what_is(x) when is_number(x) do IO.puts "#{x} is a number” end def what_is(x) when is_list(x) do IO.puts "#{inspect(x)} is a list" endend
MyModule.what_is(99) # => 99 is a numberMyModule.what_is([1,2,3]) # => [1,2,3] is a list
you can use guards with “case” too
Macros
• Macros enable to extend the language and to create DSLs (domain specific languages), in order to remove boilerplate and make code more readable.
• You won’t probably create new macros unless you’re writing a library. They should be written responsible.
Macros
• Did you know that Erlang has no “if” (as the one we have in OOP languages)?
• Elixir does have “if”, “else” and even “unless” (because Mr. Valim is a kind person), however it is actually a macro.
• These 3 macros rely on “case” which... (surprise!) it uses Pattern Matching.
Macros
http://elixir-lang.org/docs/stable/elixir/Kernel.html#if
MacrosAnother cool example for a DSL created with Macros is ExUnit, the test library that comes with Elixir:
defmodule MathTest do use ExUnit.Case test "basic operations" do assert 1 + 1 == 2 end end
macro! macro! macro!
Exceptions?
No! Pattern Matching!
case File.open("chain.exs") do { :ok, file } -> # something { :error, reason } -> # uh oh end
Pipe Operator |>Typical code in OOP / imperative programming:
people = DB.find_customersorders = Orders.for_customers(people)tax = sales_tax(orders, 2013)filing = prepare_filing(tax)We could rewrite it as...
filing = prepare_filing(sales_tax(Orders.for_customers(DB.find_customers), 2013))
Pipe Operator |>With Elixir pipe operator we can do just
filing = DB.find_customers |> Orders.for_customers |> sales_tax(2013) |> prepare_filing“|>” passes the result from the le! expression as the first argument to the right expression. Kinda like the Unix pipe “|”. It’s just useful syntax sugar.
Mix
• Mix is a build tool that ships with Elixir that provides tasks for creating, compiling, testing your application, managing its dependencies and much more.
• Kind of like rake (Ruby) on steroids.
Mix➜ ~ mix --helpmix # Runs the default task (current: "mix run")mix app.start # Starts all registered appsmix archive # Lists all archivesmix archive.build # Archives this project into a .ez filemix archive.install # Installs an archive locallymix archive.uninstall # Uninstalls archivesmix clean # Deletes generated application filesmix cmd # Executes the given commandmix compile # Compiles source filesmix deps # Lists dependencies and their statusmix deps.clean # Deletes the given dependencies' filesmix deps.compile # Compiles dependenciesmix deps.get # Gets all out of date dependenciesmix deps.unlock # Unlocks the given dependenciesmix deps.update # Updates the given dependenciesmix do # Executes the tasks separated by commamix escript.build # Builds an escript for the projectmix help # Prints help information for tasksmix hex # Prints Hex help informationmix hex.build # Builds a new package version locallymix hex.config # Reads or updates Hex configmix hex.docs # Publishes docs for packagemix hex.info # Prints Hex informationmix hex.key # Hex API key tasksmix hex.outdated # Shows outdated Hex deps for the current projectmix hex.owner # Hex package ownership tasks
mix hex.public_keys # Manages Hex public keysmix hex.publish # Publishes a new package versionmix hex.registry # Hex registry tasksmix hex.search # Searches for package namesmix hex.user # Hex user tasksmix loadconfig # Loads and persists the given configurationmix local # Lists local tasksmix local.hex # Installs Hex locallymix local.phoenix # Updates Phoenix locallymix local.public_keys # Manages public keysmix local.rebar # Installs rebar locallymix new # Creates a new Elixir projectmix phoenix.new # Creates a new Phoenix v1.1.4 applicationmix profile.fprof # Profiles the given file or expression with fprofmix run # Runs the given file or expressionmix test # Runs a project's testsiex -S mix # Starts IEx and run the default task
Mixfiledefmodule MyCoolProject.Mixfile do use Mix.Project
def project do [ app: :my_cool_projet, version: "0.0.1", deps: deps ] end
# Configuration for the OTP application def application do [mod: { MyCoolProject, [] }] end
# Returns the list of dependencies in the format: # { :foobar, git: "https://github.com/elixir-lang/foobar.git", tag: "0.1" } # # To specify particular versions, regardless of the tag, do: # { :barbat, "~> 0.1", github: "elixir-lang/barbat" } defp deps do [ {:exactor, github: "sasa1977/exactor"}, {:"erlang-serial", github: "knewter/erlang-serial", app: false} ] endend
DocTestsdefmodule MyModule do @doc ~S""" Sums two numbers
## Examples
iex> MyModule.sum(1, 2) 3
""" def sum(a, b) do a + b endend
$ mix testCompiled lib/my_module.ex..
Finished in 0.1 seconds (0.1s on load, 0.00s on tests)2 tests, 0 failures
Randomized with seed 307356
OTP
• OTP stands for Open Telecom Platform, but the name is misleading. OTP is not only for telecom related so!ware.
• It’s a bundle that includes a large number of libraries to solve problems like state management, application discovery, failure detection, hot code swapping, and server structure .
• Unfortunately, we don’t have time to talk about OTP today :/
Erlang Observeriex> :observer.start
ELIXIR FOR WEB APPS
Phoenix Framework• MVC web framework created by Chris McCord. José
Valim is working on it too.
• Tastes a little bit like Ruby on Rails, but it is not.
• Aims for high developer productivity and high application performance.
• It has powerful abstractions for creating modern web apps in 2016, such as Channels (~ web sockets).
Phoenix Framework
• Create a new project$ mix phoenix.new hello_phoenix
• Create database$ mix ecto.create
• Run server$ mix phoenix.server
Phoenix Framework
• It’s actually the top layer of a multi-layer system designed to be modular and flexible.
• The other layers include Plug (kind of like Ruby’s Rack), Ecto (kind of like ActiveRecord), and Cowboy, the Erlang HTTP server.
Phoenix Framework
• Thanks to the power of Elixir and the ease of use of Channels in Phoenix we can create web apps where we have 1 real time bi-directional data channel with every user (a websocket). And it scales, for real.
• Despite that WebSockets are the main transport for Phoenix’s channels, it also supports other transport mechanism for old browsers or embedded devices.
Phoenix Framework
• It plays nicely with the modern front-end world (ES6) by relying on Brunch, a fast and simple asset build tool.
• It’s very easy to replace Brunch by Webpack or any other hipster build tool of your choice.
• Note that Brunch requires Node.js (trollface).
Phoenix Framework
https://www.youtube.com/watch?v=3LiLjVCDEpU
Phoenix Framework
Phoenix Framework
HOW FAST IS ELIXIR?
spoiler... a lot!
http://bob.ippoli.to/haskell-for-erlangers-2014/#/cost-of-concurrency
SHOWCASE
Showcase• BSRBulb: Elixir library to control a Bluetooth Smart Bulb.
https://github.com/diacode/bsr_bulb
• Phoenix Trello: a Trello tribute with Phoenix & React.https://github.com/bigardone/phoenix-trellohttps://blog.diacode.com/trello-clone-with-phoenix-and-react-pt-1
• Phoenix Toggl: a Toggl tribute with Phoenix & React.https://github.com/bigardone/phoenix-toggl
• Elixir Toggl API Wrapperhttps://github.com/diacode/togglex
WHERE TO GO FROM
HERE?
Next steps• Watch every talk by José Valim. Really, you won’t regret.
• Books:Programming Elixir – Dave ThomasProgramming Phoenix – Chris McCord, Bruce Tate & José Valim.
• Elixir Getting Started Guide (really good!)http://elixir-lang.org/getting-started/introduction.html
• Phoenix Guide (really good!)http://www.phoenixframework.org/docs/overview
• Elixir Radarhttp://plataformatec.com.br/elixir-radar
• Madrid |> Elixir Slack (#madrid-meetup)https://elixir-slackin.herokuapp.com/
THANK YOUQuestions?