当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Elixir Kernel.use用法及代码示例


Elixir语言中 Kernel.use 相关用法介绍如下。

用法:

use(module, opts \\ [])
(宏)

在当前上下文中使用给定的模块。

调用时:

use MyModule, some: :options

调用MyModule 模块中的__using__/1 宏,将传递给use 的第二个参数作为其参数。由于__using__/1 是一个宏,所有常用的宏规则都适用,并且它的返回值应该是引用的代码,然后插入到调用 use/2 的地方。

例子

例如,要使用 Elixir 提供的 ExUnit 框架编写测试用例,开发人员应该 use ExUnit.Case 模块:

defmodule AssertionTest do
  use ExUnit.Case, async: true

  test "always pass" do
    assert true
  end
end

在此示例中,Elixir 将调用 ExUnit.Case 模块中的 __using__/1 宏,并将关键字列表 [async: true] 作为其参数。

换句话说, use/2 转换为:

defmodule AssertionTest do
  require ExUnit.Case
  ExUnit.Case.__using__(async: true)

  test "always pass" do
    assert true
  end
end

其中 ExUnit.Case 定义__using__/1 宏:

defmodule ExUnit.Case do
  defmacro __using__(opts) do
    # do something with opts
    quote do
      # return some code to inject in the caller
    end
  end
end

最佳实践

__using__/1 通常在需要将某些状态(通过模块属性)或回调(如 @before_compile ,请参阅 Module 的文档以获取更多信息)设置到调用者时使用。

__using__/1 也可用于别名、要求或导入来自不同模块的函数:

defmodule MyModule do
  defmacro __using__(_opts) do
    quote do
      import MyModule.Foo
      import MyModule.Bar
      import MyModule.Baz

      alias MyModule.Repo
    end
  end
end

但是,如果 __using__/1 所做的只是导入、别名或要求模块本身,则不要提供。例如,避免这种情况:

defmodule MyModule do
  defmacro __using__(_opts) do
    quote do
      import MyModule
    end
  end
end

在这种情况下,开发人员应该直接导入或别名模块,以便他们可以根据需要自定义这些模块,而不需要 use/2 后面的间接。

最后,开发人员还应避免在 __using__/1 回调中定义函数,除非这些函数是先前定义的 @callback 的默认实现,或者是要被覆盖的函数(参见 defoverridable/1 )。即使在这些情况下,定义函数也应视为"last resort"。

如果您想为用户模块提供一些现有函数,请将其定义在将相应导入的模块中;例如, ExUnit.Case 没有在调用 use ExUnit.Case 的模块中定义 test/3 宏,但它定义了 ExUnit.Case.test/3 并在使用时将其导入调用者。

相关用法


注:本文由纯净天空筛选整理自elixir-lang.org大神的英文原创作品 Kernel.use(module, opts \\ [])。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。