$30 off During Our Annual Pro Sale. View Details »

Sweet Elixir - Short

Sweet Elixir - Short

Around 60% of telecom passes through Erlang. Facebook uses it and RabbitMQ is built on it. It’s fast, concurrent, distributed, but its Prolog-inspired syntax leaves much to be desired. Ruby is beautiful and powerful, but struggles at scale and treats concurrency as a second class citizen. Elixir - a young, functional, meta programming language - aims to resolve this mighty conflict by providing a rosy syntax inspired by Ruby that compiles to Erlang VM compatible bytecode.
Together we’ll take a guided tour of Elixir basics and functional programming concepts like pattern matching, pipelines and tail-call recursion. From there we’ll explore the distributed and concurrent nature of Elixir, the fault tolerant features of OTP, and ways you can leverage Elixir in your existing architectures today.

Whether you roll with a Mac, Windows or Linux everyone will leave an Elixir programmer.

Ryan Cromwell

May 31, 2014
Tweet

More Decks by Ryan Cromwell

Other Decks in Programming

Transcript

  1. Pipeline What’s Elixir? |> Types, Functions, Modules |> Pattern Matching

    |> Maps, Structs, & Protocols |> Pipelines |> Processes |> OTP, Phoenix
  2. Mac #Mac! $> brew update! $> brew install erlang! $>

    brew install elixir! ! #Linux! <Your package manager here>! ! #Windows! PS> cinst elixir
  3. is_number 1 ! ! ! ! ! ! ! !

    ! ! ! ! ! #=> true! ! is_integer 1! ! ! ! ! ! ! ! ! ! ! ! ! #=> true! ! is_number 2.1! ! ! ! ! ! ! ! ! ! ! ! #=> true! ! is_float 2.1! ! ! ! ! ! ! ! ! ! ! ! ! #=> true! ! is_integer 2.1! ! ! ! ! ! ! ! ! ! ! ! #=> false
  4. 1 == 1.0!! ! ! ! ! ! ! !

    ! ! ! ! ! ! #=> true! ! 1 === 1.0! ! ! ! ! ! ! ! ! ! ! ! ! ! #=> false
  5. is_boolean true! ! ! ! ! ! ! ! !

    ! ! #=> true! ! true or false! ! ! ! ! ! ! ! ! ! ! ! #=> true! ! true || false! ! ! ! ! ! ! ! ! ! ! ! #=> true
  6. is_atom :selfConf!! ! ! ! ! ! ! ! !

    #=> true! ! is_atom true! ! ! ! ! ! ! ! ! ! ! ! ! #=> true
  7. is_list [1,2,3]! ! ! ! ! ! ! ! !

    ! ! #=> true! ! length [1,2,3]! ! ! ! ! ! ! ! ! ! ! ! #=> 3! ! [1,2] ++ [3,4]! ! ! ! ! ! ! ! ! ! ! ! #=> [1,2,3,4]! ! iex> h Enum! ! iex> h Stream
  8. is_tuple {1, “b”, :c}! ! ! ! ! ! !

    ! #=> true! ! elem! {1, “b”, :c}, 1!! ! ! ! ! ! ! #=> “b”! ! t = {1, “b”, :c}! set_elem t, 2, :d!! ! ! ! ! ! ! ! ! #=> {1, “b”, :d}! ! Integer.parse “1.0a3”!! ! ! ! ! ! ! #=> {1, “.0a3”}
  9. is_list ‘hello’! ! ! ! ! ! ! ! !

    ! ! #=> true! ! is_list “hello”! ! ! ! ! ! ! ! ! ! ! #=> true! ! is_binary “hello”!! ! ! ! ! ! ! ! ! #=> true
  10. “hello” <> “ world”! ! ! ! ! ! !

    ! ! ! #=> “hello world”! ! who = “ryan”! “hello #{who}”! ! ! ! ! ! ! ! ! ! ! ! ! #=> “hello ryan”
  11. add = fn (x, y) -> x + y end!

    ! add.(2,2)! ! ! ! ! ! ! ! ! ! ! #=> 4
  12. do_calc = fn(x,y, calc) -> calc.(x,y) end! ! do_calc.(2,3, add)!

    ! ! ! ! ! ! ! ! #=> 5! ! do_calc.(2,4, &(&1 * &2))! ! ! ! ! #=> 8
  13. defmodule Weather do! ! def celsius_to_fahrenheit(celsius) do! ! ! (celsius

    * 1.8) + 32! ! end! ! ! def boiling, do: 100! ! def freezing, do: 0! end! ! Weather.celsius_to_fahrenheit(20) ! ! #=> 68.0
  14. import alias defmodule USWeather do! ! import Weather, only: [freezing:

    0,! ! ! ! celsius_to_fahrenheit: 1]! ! ! alias :math, as Math! ! ! def cold_in_michigan do! ! ! celsius_to_fahrenheit(freezing - 10)! ! end! end
  15. [head | tail] = [1,2,3,4,5]! ! head! ! ! !

    ! ! ! ! ! ! ! ! ! ! ! ! ! ! #=> 1! ! tail! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! #=> [2,3,4,5]
  16. {a,b,c}! = {1,”b”,:c}! ! a!! ! ! ! ! !

    ! ! ! ! ! ! ! ! ! ! ! ! ! #=> 1! ! b!! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! #=> “b”! ! c!! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! #=> :c
  17. Control Flow calculate = fn expression ->! case expression do!

    {:+, num1, num2} -> num1 + num2! {:-, num1, num2} -> num1 - num2! {:*, num1, 0} -> 0! {:*, num1, num2} -> num1 * num2! end! end
  18. defmodule Countdown do! def run(from, to) when from >= to

    do! run(from, to, from)! end! ! def run(_from, to, current) when to == current do! IO.puts to! IO.puts "Done!"! end! ! def run(from, to, current) do! IO.puts current! run(from, to, current - 1)! end! end Function
  19. defmodule PersonPrefixer do! def prefix(p = %{ gender: :male }),

    do: "Mr."! def prefix(p = %{ gender: :female }), do: "Mrs."! def prefix(p), do: ""! end! ! PersonPrefixer.prefix %{first: “Sandy”, gender: :female} #=> “Mrs”
  20. Maps speaker = %{! first: “Ryan”,! last: “Cromwell”,! twitter: “@cromwellryan”,!

    “home town” => “Dayton, OH”! }! ! speaker[:twitter] #=> “@cromwellryan”! ! speaker[“Home Town”] #=> “Dayton, OH”
  21. Protocols defprotocol Good do! @doc "Returns true if data is

    considered good"! def good?(data)! end
  22. Ad-hoc Polymorphism defimpl Good, for: Kid do! ! def good?(%Kid{name:

    "Ryan"}), do: true! ! def good?(_), do: false! end! ! Good.good? %Kid{name: "Ryan"}! ! ! ! ! ! ! ! #> true! Good.good? %Kid{name: "Ben"}!! ! ! ! ! ! ! ! #> false
  23. Enum.map [1,2,3,4], fn (x) -> x * 2 !! !

    ! ! ! #=> [2,4,6,8]! ! [1,2,3,4] |> Enum.map(fn (x) -> x *2)! ! ! ! ! #=> [2,4,6,8]
  24. lines = String.split file_content, "\n"! lines = Stream.filter lines, &(String.length(&1)

    > 0)! lengths = Stream.map lines, &(String.split &1)! triangles = Stream.map lengths, &(list_to_tuple &1)! classifications = Stream.map triangles, &( %{sides: &1, classification: Classifier.classify &1} )! ! messages = Stream.map classifications, &( "Triangle #{inspect &1[:sides]} is #{&1[:classification]}" )! result = Enum.join(messages, "\n")! ! IO.puts result before
  25. file_content! |> String.split("\n")! |> Stream.filter( &(String.length(&1) > 0) )! |>

    Stream.map( &(String.split &1) )! |> Stream.map( &(list_to_tuple &1) )! |> Stream.map( &(%{sides: &1, class: Classifier.classify &1}) )! |> Stream.map( &("Triangle #{inspect &1[:sides]} is #{&1[:class]}") )! |> Enum.join("\n")! |> IO.puts! after
  26. pid = spawn fn ->! receive do! {sender, :ping} ->!

    IO.puts "Got ping"! send sender, :pong! end! end
  27. Inspired by Rails defmodule ChatDemoEx.Router do! use Phoenix.Router! use Phoenix.Router.Socket,

    mount: "/ws"! ! plug Plug.Static, at: "/static", from: :chat_demo_ex! get "/", ChatDemoEx.Controllers.Pages, :index, as: :page! ! channel "rooms", Chat.Channels.Rooms! end
  28. defmodule Chat.Channels.Rooms do! use Phoenix.Channel! ! def event(socket, "new:message", message)

    do! broadcast socket, "new:message", message! ! socket! end! end Elixir
  29. Resources ‣ elixir-lang.org ‣ elixirsips.com ‣ elixirconf.com (July 25-26) !

    ‣ PragProg: Programming Elixir ! ‣ github.com/cromwellryan/sweetelixir ‣ http://bit.ly/sweetelixir-short