Explicitness as a Weakness?

Care to elaborate on the “pick out bugs easily” part?

If this is primarily about macros then it is important remember that there are always tradeoffs involved. Example:

defmodule Demo do
  use Attr

  attr :three
  attr :two
  attr :one

end

IO.inspect(Demo.get_attrs()) # [:one, :two, :three]
                             # ???

Evidently it’s equivalent to:

defmodule Demo1 do

  def get_attrs(),
    do: [:one, :two, :three]

end

which isn’t transparent on first sight unless you are already familiar with

# Blatantly plagiarized from Plug.Build
defmodule Attr do
  defmacro __using__(_opts) do
    quote do
      import Attr, only: [attr: 1]

      Module.register_attribute(__MODULE__, :attrs, accumulate: :true)
      @before_compile Attr
    end
  end

  defmacro __before_compile__(env) do
    attrs = Module.get_attribute(env.module, :attrs)

    quote do
      def get_attrs() do
        unquote(attrs)
      end
    end
  end

  defmacro attr(attr) do
    quote do
      @attrs unquote(attr)
    end
  end
end

In a way the macro invocation is an alternate representation (compression) of the code that it will leave behind. That succinctness suppresses certain details (which may be desired) some of which could improve clarity (e.g. showing how the resulting code connects and relates to the “rest of the world”). The only way to compensate for that lack of exposed detail is to understand what the macro actually represents. So improved succinctness may also increase the cognitive load for anybody trying to comprehend what the code does.

In many situations the tradeoff is worth it. But every case is still is a balancing act between the benefits of succinctness, reuse potential and the effect on clarity and comprehensibility. Not all abstractions are created equal.

2 Likes