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

Fun with Elixir Macros

Fun with Elixir Macros

Lightning talk from ElixirConfEU 2018

Tymon Tobolski

April 16, 2018
Tweet

More Decks by Tymon Tobolski

Other Decks in Programming

Transcript

  1. defmodule AppRouter do use Plug.Router plug :match plug :dispatch get

    "/hello" do send_resp(conn, 200, "world") end match _ do send_resp(conn, 404, "oops") end end
  2. defmodule Tesla do defmacro __using__(_) do quote do Module.register_attribute(__MODULE__, :middleware,

    accumulate: true) @before_compile Tesla import Tesla, only: [plug: 1, plug: 2] def request(method, path), do: Tesla.request(__MODULE__, {method, path}) end end # ...
  3. defmodule Cabify do Module.register_attribute(__MODULE__, :middleware, accumulate: true) @before_compile Tesla @middleware

    {Tesla.Middleware.Base, "https://cabify.com"} @middleware {Tesla.Middleware.JSON, []} end
  4. defmodule Cabify do # ... def __middleware__ do [ {Tesla.Middleware.Base,

    "https://cabify.com"}, {Tesla.Middleware.JSON, []} ] end end
  5. defmodule Tesla do def request(module, env) do stack = module.__middleware__

    run(env, stack) end def run(env, []), do: make_request(env) def run(env, [{module, opts} | rest]), do: apply(module, :call, [env, rest, opts]) end
  6. defmodule Tesla.Middleware.Base do def call({method, path}, next, base) do Tesla.run({method,

    base <> path}, next) end end defmodule Tesla.Middleware.JSON do def call({method, path}, next, _opts) do Tesla.run({method, path <> ".json"}, next) end end
  7. - Simple & powerful API - call(env, next, opts) -

    Allows hot reloading of middlewares on production system - Full implementation at github.com/teamon/tesla (be sure to use 1.0.0-beta.1) - Don’t be afraid of macros :)