Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Elixir

 Elixir

Looking at the programming language Elixir

Joseph Wilk

August 20, 2013
Tweet

More Decks by Joseph Wilk

Other Decks in Technology

Transcript

  1. Elixir
    Joseph Wilk

    View Slide

  2. Erlang VM

    View Slide

  3. View Slide

  4. Blocks
    Syntax
    Signals
    Concurrency

    View Slide

  5. OTP
    Pattern
    Matching
    Macros

    View Slide

  6. Macros
    Destructing
    Pattern Matching

    View Slide

  7. Pattern
    Matching
    |> (Pipe operator)
    DCGs /
    Monad

    View Slide

  8. Elixir Erlang
    VM
    BEAM
    byte code
    compiles

    View Slide

  9. Elixir Erlang
    VM
    BEAM
    byte code
    compiles
    Invoke Erlang 0 runtime cost
    and visa-versa

    View Slide

  10. Interop
    :erlang.make_tuple(10, [])
    -module(bstring).
    -export([downcase/1]).
    downcase(Bin) ->
    'Elixir.String':downcase(Bin).
    Erlang in Elixir
    Elixir in Erlang

    View Slide

  11. Install
    $ brew install elixir
    iex, mix, elixir
    $ wget http://bit.ly/1aN4Ftt
    Erlang, version R16B
    https://www.erlang-solutions.com/downloads/download-erlang-otp
    $ brew tap homebrew/versions
    $ brew link erlang-r16
    Elixir

    View Slide

  12. $ brew install elixir
    iex, mix, elixir
    $ wget http://bit.ly/1aN4Ftt
    Erlang, version R16B
    https://www.erlang-solutions.com/downloads/download-erlang-otp
    Elixir
    $ brew tap homebrew/versions
    $ brew link erlang-r16
    Install
    iex, mix, elixir

    View Slide

  13. Anti Pattern
    OO
    Object Orientated Programming

    View Slide

  14. No Objects
    No Classes
    No Inheritance
    defmodule Yes do
    use Amrita.Sweet
    import Support
    end

    View Slide

  15. Everything is an
    Expressions
    https://github.com/joearms/erl2

    View Slide

  16. defmodule A do
    def ping do
    "pong"
    end
    IO.puts "ping"
    end
    defmodule B do
    def ping do
    A.ping
    end
    end
    defmodule C do
    def ping do
    B.ping
    end
    end

    View Slide

  17. Modules
    Pattern matching
    Polymorphism > protocols
    Records
    Macros

    View Slide

  18. { x, y, _ } = { 10, 2, 3 }
    IO.inspect x #=> 10
    IO.inspect y #=> 2
    Pattern Matching

    View Slide

  19. if is_list(thing) && !Enum.empty?(thing) do
    IO.puts "matches"
    else
    IO.puts "no match"
    end
    case thing do
    [_] -> IO.puts "matches"
    _ -> IO.puts "no match"
    end
    Pattern Matching

    View Slide

  20. Pattern Matching
    defmodule Eating do
    def meeting([head| tail]) do
    [rules(head) | meeting(tail)]
    end
    def meeting([]) do
    []
    end
    def rules({ :lion, :cat }), do: "lion eats cat"
    def rules({ :lion, :shark }), do: "shark eats lion"
    def rules({ :rabbit, other }), do: "rabbit eats #{other}"
    def rules({ a, b }), do: "#{a} eats #{b}"
    def rules({ a }), do: "#{a} eats itself"
    def rules(_), do: "nothing gets eaten"
    end
    Eating.meeting([{:lion, :cat}, {:lion, :shark}])

    View Slide

  21. Protocols
    defprotocol Enumerable do
    def reduce(item)
    #...
    end
    end
    defimpl Enumerable, for: Set do
    def reduce(set, acc, fun), do: Set.reduce(set, acc, fun)
    end
    Enum.reduce HashSet.new, [], fn element, accum ->
    List.concat(element, accum)
    end

    View Slide

  22. Records
    compile time pattern
    defrecord ExUnit.Test, [:name, :case, :failure, :time] do
    @moduledoc """
    A record that keeps information about the test.
    It is received by formatters and also accessible
    in the metadata under the key `:test`.
    """
    end
    def handle_cast({:test_finished, ExUnit.Test[failure: nil] = test}, config) do
    if config.trace do
    IO.puts success(trace_test_result(test))
    else
    IO.write success(".")
    end
    { :noreply, config.update_tests_counter(&1 + 1) }
    end

    View Slide

  23. Macros
    defmacro hello do
    end

    View Slide

  24. Controlling
    resolution of scope
    Domain specific
    language
    (or something-fast something-slow)
    10 |> IO.puts

    View Slide

  25. { name, meta, args }
    [...]
    :atoms
    ints/strings

    View Slide

  26. { :+, [line: 1], [1,2] }
    1 + 2

    View Slide

  27. { _, _, _ }
    defmacro hello do
    end
    Macro
    tuples
    { _, _, _ }
    tuples

    View Slide

  28. Amrita
    https://github.com/josephwilk/amrita
    A polite, well mannered and thoroughly upstanding testing framework for Elixir
    fact "about factorial" do
    factorial(0) |> ! 0
    factorial(0) |> 1
    list_of_factorials = Enum.map 0..3, fn n -> factorial(n) end
    list_of_factorials |> contains 1
    list_of_factorials |> !contains 2
    list_of_factorials |> [ _, 1, _, 6 ]
    end

    View Slide

  29. fact "mock with a _ wildcard" do
    provided [MocksTest.Funk.hip?(_) |> false]
    Funk.hip?(:yes) |> falsey
    Funk.hip?(:whatever) |> falsey
    end
    end

    View Slide

  30. fact "mock with a _ wildcard" do
    provided [MocksTest.Funk.hip?(_) |> false]
    Funk.hip?(:yes) |> falsey
    Funk.hip?(:whatever) |> falsey
    end
    end
    |>(MocksTest.Funk.hip?(_), false)

    View Slide

  31. fact "mock with a _ wildcard" do
    provided [MocksTest.Funk.hip?(_) |> false]
    Funk.hip?(:yes) |> falsey
    Funk.hip?(:whatever) |> falsey
    end
    end
    [{ :|>, [line: 2], [ , false] }]
    { {:., [line: 2], } , [line: 2], [:_] }
    [ { :__aliases__, [line: 2], [:MocksTest, :Funk] }, :hip? ]
    |>(MocksTest.Funk.hip?(_), false)

    View Slide

  32. defmodule Provided.Parse do
    defexception Error, form: [] do
    def message(exception) do
    "Amrita could not understand your `provided`:\n" <>
    " " <> Macro.to_string(exception.form) <> "\n" <>
    " Make sure it uses this format: [Module.fun |> :return_value]"
    end
    end
    def prerequisites(forms) do
    prerequisites = Enum.map(forms, fn form -> extract(form) end)
    Provided.Prerequisites.new(prerequisites)
    end
    defp extract({:|>, _, [{fun, _, args}, value]}) do
    { module_name, function_name } = extract(fun)
    { module_name, function_name, args, value }
    end
    defp extract({:., _, [ns, method_name]}) do
    { extract(ns), method_name }
    end
    defp extract({:__aliases__, _, ns}) do
    Module.concat ns
    end
    defp extract(form) do
    raise Error.new(form: form)
    end
    end

    View Slide

  33. defmodule Provided.Parse do
    defexception Error, form: [] do
    def message(exception) do
    "Amrita could not understand your `provided`:\n" <>
    " " <> Macro.to_string(exception.form) <> "\n" <>
    " Make sure it uses this format: [Module.fun |> :return_value]"
    end
    end
    def prerequisites(forms) do
    prerequisites = Enum.map(forms, fn form -> extract(form) end)
    Provided.Prerequisites.new(prerequisites)
    end
    defp extract({:|>, _, [{fun, _, args}, value]}) do
    { module_name, function_name } = extract(fun)
    { module_name, function_name, args, value }
    end
    defp extract({:., _, [ns, method_name]}) do
    { extract(ns), method_name }
    end
    defp extract({:__aliases__, _, ns}) do
    Module.concat ns
    end
    defp extract(form) do
    raise Error.new(form: form)
    end
    end

    View Slide

  34. iex> quote do: IO.puts
    iex> quote do
    fn(x) -> x end
    end

    View Slide

  35. Immutability
    “Elixir assignments are compiled down to Static Single Assignment.”
    defmodule Immutable do
    def mutation do
    x = 1 # => v0 = 1
    x = 2 # => v1 = 2
    x = 3 # => v2 = 3
    end
    end

    View Slide

  36. Performance

    View Slide

  37. View Slide

  38. Thanks

    View Slide