Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Chapter 23

programming-elixir-1.6/chapter-23.livemd

Chapter 23

Exercise: LinkingModules-BehavioursAndUse-1

name and args are parameters passed to a macro, which are the tuples representing their code. Therefore, unquote is used to evaluate them. On the other hand, result is just a value, so unquote is not necessary.

Exercise: LinkingModules-BehavioursAndUse-2 & 3

defmodule Tracer do
  import IO.ANSI

  def dump_args(args) do
    args |> Enum.map(&inspect/1) |> Enum.join(", ")
  end

  def dump_defn(name, args) do
    "#{name}(#{dump_args(args)})"
  end

  def add_tracer(definition = {name, _, args}, do: content) do
    quote do
      Kernel.def unquote(definition) do
        IO.puts([
          red(),
          "==> call:   #{Tracer.dump_defn(unquote(name), unquote(args))}",
          default_color()
        ])

        result = unquote(content)
        IO.puts([green(), "<== result: #{result}", default_color()])
        result
      end
    end
  end

  defmacro def({:when, _, [definition | _]}, do: content) do
    add_tracer(definition, do: content)
  end

  defmacro def(definition, do: content) do
    add_tracer(definition, do: content)
  end

  defmacro __using__(_opts) do
    quote do
      import Kernel, except: [def: 2]
      import unquote(__MODULE__), only: [def: 2]
    end
  end
end

defmodule Test do
  use Tracer
  def puts_sum_three(a, b, c) when a == 1 and b == 2, do: IO.inspect(a + b + c)
  def add_list(list), do: Enum.reduce(list, 0, &amp;+/2)
end

Test.puts_sum_three(1, 2, 3)
Test.add_list([5, 6, 7, 8])

Exercise: LinkingModules-BehavioursAndUse-3

If add a method definition with a guard clause to the Test module, the value of definition has changed as follows.

{:when, [line: 41],
 [
   {:puts_sum_three, [line: 41],
    [{:a, [line: 41], nil}, {:b, [line: 41], nil}, {:c, [line: 41], nil}]},
   {:and, [line: 41],
    [
      {:==, [line: 41], [{:a, [line: 41], nil}, 1]},
      {:==, [line: 41], [{:b, [line: 41], nil}, 2]}
    ]}
 ]}

And then unquote(args) never returned. I don’t know why, maybe because args is not a tuple for representing the code, but a list.