# Attributes with function name

**URL:** <https://forum.elixirforum.com/t/attributes-with-function-name/38988>\
**Category:** Questions\
**Tags:** metaprogramming, troubleshooting, module-attribute\
**Created:** [April 15, 2021, 2:39pm UTC](https://forum.elixirforum.com/t/attributes-with-function-name/38988 "2021-04-15T14:39:43Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![enobat](https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/e/ad7895/32.png) [@enobat](https://forum.elixirforum.com/u/enobat)\
**Post date:** [April 15, 2021, 2:39pm UTC](https://forum.elixirforum.com/t/attributes-with-function-name/38988/1 "2021-04-15T14:39:43Z")

</div>

Can you use custom attributes similar to `@impl` or `@behaviour`, but rather than using a callback function, only the function name is used (e.g. `@description Mod.fun`).

```elixir
# A.ex
defmodule A do
  use C

  @description1 "function11 returns :ok"
  def function1(_a) do
    :ok
  end

  @description2 A.function1
  def function2(_b) do
    :ok
  end
end

```

In the example above, the `@description1` attribute is valid, since what follows is a string. Then, in `@description2` fails since it tries to get a value, but instead I wish to get the name of the method (i.e. `A.function1`).

```elixir
defmodule B do
  @behaviour Bar
  @callback foo
end

```

Some elixir modules are able to do something similar. For example, you can set modules/methods to `@behaviour` and `@callback`. Can something similar be created?  
Thanks.

---

<div class="post-metadata">

**Author:** ![Nicd](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/nicd/32/2357_2.png) [@Nicd](https://forum.elixirforum.com/u/Nicd)\
**Post date:** [April 15, 2021, 2:51pm UTC](https://forum.elixirforum.com/t/attributes-with-function-name/38988/2 "2021-04-15T14:51:58Z")

</div>

> [@enobat](#):
>
> `@description2 A.function1`

You could use a function reference there, like

```elixir
@description &A.function1/1

```

But I’m wondering what you want to do with it? Obviously module A would then need to be compiled first.

---

<div class="post-metadata">

**Author:** ![al2o3cr](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/al2o3cr/32/3457_2.png) [@al2o3cr](https://forum.elixirforum.com/u/al2o3cr)\
**Post date:** [April 15, 2021, 2:52pm UTC](https://forum.elixirforum.com/t/attributes-with-function-name/38988/3 "2021-04-15T14:52:33Z")

</div>

You can capture a function with `&` in a module attribute:

```elixir
defmodule Blergh do
  @some_attr &Blergh.foo/1
  def read_some_attr, do: @some_attr

  def foo(arg), do: IO.inspect(arg)
end

iex(2)> Blergh.read_some_attr.("hello world")
"hello world"
"hello world"

```

Note that the name must include the module - just spelling it `foo/1` will return a `CompileError`.

---

<div class="post-metadata">

**Author:** ![enobat](https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/e/ad7895/32.png) [@enobat](https://forum.elixirforum.com/u/enobat)\
**Post date:** [April 15, 2021, 3:14pm UTC](https://forum.elixirforum.com/t/attributes-with-function-name/38988/4 "2021-04-15T15:14:44Z")

</div>

I’m developing static checker, so all modules need to be compiled first, before analysed.

For example, the `@description` attribute can either be set to a string, or otherwise refer to another function (which I can process later on).

```elixir
# A.ex
defmodule A do
  use B

  @description "function1/0 returns :ok"
  def function1() do
    :ok
  end

  @description A.function1
  def function2() do
    :ok
  end
end

```

```elixir
# B.ex
defmodule B do
  defmacro __using__ (_) do
    quote do
      import B
      Module.register_attribute( __MODULE__ , :description, accumulate: true, persist: true)
      Module.register_attribute( __MODULE__ , :test, accumulate: true, persist: true)
      @after_compile B
    end
  end

  def __on_definition__ (env, _access, name, args, _guards, _body) do
    IO.puts("Reached on_definition")
    desc = Module.get_attribute(env.module, :description) |> hd()
    Module.delete_attribute(env.module, :description)
    Module.put_attribute(env.module, :test, {name, length(args), desc})
  end

  def __after_compile__ (_env, bytecode) do
    IO.puts("Reached after_compile")
    # Gets debug_info chunk from BEAM file
    chunks =
     case :beam_lib.chunks(bytecode, [:debug_info]) do
        {:ok, {_mod, chunks}} -> chunks
        {:error, _, error} -> throw("Error: #{inspect(error)}")
      end
    # Gets the (extended) Elixir abstract syntax tree from debug_info chunk
    dbgi_map =
      case chunks[:debug_info] do
        {:debug_info_v1, :elixir_erl, metadata} ->
          case metadata do
            {:elixir_v1, map, _} ->
              # Erlang extended AST available
              map
          end
        x ->
          throw("Error: #{inspect(x)}")
      end
    dbgi_map[:attributes]
    |> IO.inspect
  end
end

```

This outputs the following. `&A.function1/0` is saved which is what was needed:

```elixir
[description: "function1/0 returns :ok", description: &A.function1/0]

```

Compared to the [Elixir module](https://hexdocs.pm/elixir/Module.html), you can set functions directly `@callback foo`. Can something cleaner (without the &a/0) be achieved?
