在我的大多数模块中,我
require Logger
Run Code Online (Sandbox Code Playgroud)
然后做一些日志记录.在我不这样做的模块中,我经常进行更改,包括添加一些日志记录,然后我必须标记我正在使用记录器.
require在每个模块中使用Logger 的成本是多少?有没有一种干净的方法可以随时require使用Logger而不在每个模块中提及它?
主要目的require是提供对所需模块中声明的宏的访问:
模块中的公共函数是全局可用的,但是为了使用宏,您需要通过要求定义它们的模块来选择加入
- 来自docs forKernel.SpecialForms.require/2
此外,来自Elixir指南:
宏是词汇:全局注入代码或宏是不可能的.要使用宏,您需要显式地要求或导入定义宏的模块.
重点是我的.这样做是为了您自己的安全:与函数不同,宏可能会彻底修改您现有的AST.Logger这是这种行为的一个很好的例子:当级别小于compile_time_purge_levelconfig中指定的级别时,它不会在AST中留下任何痕迹.没有单一的noop.没有.虚无.
这基本上是为什么Logger实现为宏.
有两种方法可以克服这种行为.
1.简单.不建议.
将您自己的包装器Logger作为一个函数:
defmodule Log do
require Logger
def log(whatever), do: Logger.log(whatever)
end
Run Code Online (Sandbox Code Playgroud)
Log.log现在到处都可用(因为它是一个功能.)
缺点:
noop调用Log.log左侧debug.这可能会影响性能.Logger必须是宏)将变得无用 - 你无法获取日志行的行号,模块等因为它们总是会给宏调用的站点(来自@NathanielWaisbrot)2.正确.推荐的.
制作自己的MyApp.Utils模块,但每个项目中都存在比todo-or-tictactoe-exercise略复杂的模块.在此模块中,保存所有实用程序功能等,实现宏回调__using__:
defmodule MyApp.Utils do
defmacro __using__(opts \\ []) do
quote do
require Logger
require MyApp.Utils # if this module has macros itself
def helper, do: Logger.log("Hey, I am always included")
...
end
...
end
end
Run Code Online (Sandbox Code Playgroud)
是的,现在在所有模块中使用Logger你必须use MyApp.Utils明确,但由于它包含在应用程序范围内使用的方便助手,因此Logger它本身是免费的.