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

Avatar for Wu Qing

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