【问题标题】:Why is Elixir Logger composed of Macros?为什么 Elixir Logger 由 Macros 组成?
【发布时间】:2017-03-05 01:19:28
【问题描述】:

今天不得不在我的一个应用程序中使用Logger,并记得I needed to call require Logger first。所以我决定看一下Logger source code,看看为什么debuginfoerror等是宏而不是简单的函数。

从代码来看,debuginfo 等的宏(甚至它们的底层函数)看起来非常简单。难道不能简单地将它们导出为方法而不是宏吗?


来自 Logger 代码:

  defmacro log(level, chardata_or_fn, metadata \\ []) do
    macro_log(level, chardata_or_fn, metadata, __CALLER__)
  end

  defp macro_log(level, data, metadata, caller) do
    %{module: module, function: fun, file: file, line: line} = caller

    caller =
      compile_time_application ++
        [module: module, function: form_fa(fun), file: file, line: line]

    quote do
      Logger.bare_log(unquote(level), unquote(data), unquote(caller) ++ unquote(metadata))
    end
end

据我所知,将它们变成函数而不是宏会更简单。

【问题讨论】:

    标签: macros metaprogramming elixir


    【解决方案1】:

    这可能是因为__CALLER__ 特殊形式提供了有关调用上下文的信息,包括文件和行,但仅在宏中可用。

    【讨论】:

    • 是的,查看__CALLER__ 文档,这是有道理的。我只是假设它就像__DIR__ 并且可以在任何地方访问。
    • 宏还允许您使用请求的日志级别进行编译。当使用日志级别error 进行编译时,所有对调试日志的调用都会从编译文件中完全删除。没有“if log_level > something”,这使得它超级快。
    【解决方案2】:

    事实证明,另一个原因是调用代码可以在编译期间为应用程序不需要的日志级别剥离。

    来自ElixirForum discussion

    这是为了让代码完全不存在您不想要的日志记录级别,因此代码甚至不会被调用并且不会导致速度损失,因此您只需为您正在积极记录的日志记录级别付费。

    如果您使用:compile_time_purge_level,则可以在编译时将整个 Logger 调用从代码中剥离出来

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-21
      • 1970-01-01
      相关资源
      最近更新 更多