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

Gentle Introduction to Elixir Macros

Gentle Introduction to Elixir Macros

Presented at June 2017 meetup of Elixir Sydney
https://www.meetup.com/sydney-ex/events/239476421/
and Elixir Camp 2 (April 21–24, 2017) in Camp Wombaroo, Mittagong, NSW

Wu Qing

June 07, 2017
Tweet

More Decks by Wu Qing

Other Decks in Programming

Transcript

  1. Why Macros — Powerful — Common in open source projects

    — Elixir itself — Phoenix — Plug — Ecto
  2. AST examples iex(1)> quote do: 1+2 {:+, [context: Elixir, import:

    Kernel], [1, 2]} iex(2)> quote do: IO.puts "hello" {{:., [], [{:__aliases__, [alias: false], [:IO]}, :puts]}, [], ["hello"]}
  3. AST block example iex(7)> quote do ...(7)> a = 3

    ...(7)> b = 2 ...(7)> a * b ...(7)> end {:__block__, [], [{:=, [], [{:a, [], Elixir}, 3]}, {:=, [], [{:b, [], Elixir}, 2]}, {:*, [context: Elixir, import: Kernel], [{:a, [], Elixir}, {:b, [], Elixir}]}]}
  4. macro example in Ecto defmodule Weather do use Ecto.Schema #

    weather is the DB table schema "weather" do field :city, :string field :temp_lo, :integer field :temp_hi, :integer ... end end Source
  5. Define our own macro defmodule MyIf do defmacro if1(condition, do:

    action) do quote do case unquote(condition) do true -> unquote(action) _ -> nil end end end end
  6. Simple timer defmodule SimpleTimer do defmacro simple_timer(message, action) do quote

    do start_time = DateTime.utc_now IO.puts "starting to #{unquote(message)} at #{DateTime.to_iso8601 start_time}" unquote(action) end_time = DateTime.utc_now IO.puts "finished at #{DateTime.to_iso8601 end_time}" duration = DateTime.to_unix(end_time, :microsecond) - DateTime.to_unix(start_time, :microsecond) IO.puts "Duration: #{duration} microseconds" end end end
  7. Summary 1. quote do ... end to get AST 2.

    unquote to inject code into AST 3. Macros accept AST and return AST