elixir before_compile && on_definition 简单使用

elixir 提供了一些方便的模块属性,可以让我们方便的进行elixir 的扩展(尤其是进行元编程的时候)
比如elixir_agent 就使用到了before_compile以及on_definition ,方便进行trace 的处理

on_definition 的简单使用

  • 参考demo

内容来自官方,可以实现输出函数的一些信息

 
defmodule Hooks do
  def on_def(_env, kind, name, args, guards, body) do
    IO.puts("Defining #{kind} named #{name} with args:")
    IO.inspect(args)
    IO.puts("and guards")
    IO.inspect(guards)
    IO.puts("and body")
    IO.puts(Macro.to_string(body))
  end
end
 
defmodule MyModule do
  @on_definition {Hooks, :on_def}
 
  def hello(arg) when is_binary(arg) or is_list(arg) do
    "Hello" <> to_string(arg)
  end
 
  def hello(_) do
    :ok
  end
end

before_compile 的简单使用

  • 参考demo
defmodule MyModule do
  @before_compile {Dalong, :__before_compile__}
  def hello(arg) when is_binary(arg) or is_list(arg) do
    "Hello" <> to_string(arg)
  end
  def hello(_) do
    :ok
  end
end

Dalong 模块中__before_compile__ 的定义

defmacro __before_compile__(env) do
    IO.puts "Before compilation!"
    IO.inspect env
    quote do
       IO.puts "Before compilation!"
    end
end

elixir_agent 的使用

elixir_agent 的使用是自己开发了一个macro,通过use 统一导入,使用如下

 defmacro __using__(_args) do
    quote do
      require NewRelic
      require NewRelic.Tracer.Macro
      require NewRelic.Tracer.Report
      Module.register_attribute(__MODULE__, :nr_tracers, accumulate: true)
      Module.register_attribute(__MODULE__, :nr_last_tracer, accumulate: false)
      @before_compile NewRelic.Tracer.Macro
      @on_definition NewRelic.Tracer.Macro
    end
  end

说明

elixir 的一些玩法比较有意思,看似缺少一些语言的能力,但是kernel 提供的其他功能,实现起来反而更加灵活强大,以下参考链接中对于上述属性
有完整的介绍可以看看

参考资料

https://hexdocs.pm/elixir/1.14.5/Module.html
https://github.com/newrelic/elixir_agent

posted on 2024-01-15 10:28  荣锋亮  阅读(6)  评论(0编辑  收藏  举报

导航