药剂:使用vs导入

useimport什么区别?

http://elixir-lang.org/docs/stable/elixir/Kernel.html#use/2

使用是一个简单的机制来使用给定的模块到当前的上下文中

http://elixir-lang.org/docs/stable/elixir/Kernel.SpecialForms.html#import/2

从其他模块导入函数和macros

看起来像一个区别是import让我们挑选特定的function/macros,而use带来的一切。

还有其他的区别吗? 你什么时候使用一个?

import Moduleimport Module所有function和macros取消为您的模块。

require Module允许您使用Modulemacros,但不导入它们。 ( Modulefunction始终可用名称空间。)

use Module首先requires模块,然后调用Module上的__using__macros。

考虑以下:

 defmodule ModA do defmacro __using__(_opts) do IO.puts "You are USING ModA" end def moda() do IO.puts "Inside ModA" end end defmodule ModB do use ModA def modb() do IO.puts "Inside ModB" moda() # <- ModA was not imported, this function doesn't exist end end 

这不会编译为ModA.moda()尚未导入到ModB

以下将编译:

 defmodule ModA do defmacro __using__(_opts) do IO.puts "You are USING ModA" quote do # <-- import ModA # <-- end # <-- end def moda() do IO.puts "Inside ModA" end end defmodule ModB do use ModA def modb() do IO.puts "Inside ModB" moda() # <-- all good now end end 

当你use d ModA它会生成一个插入ModBimport语句。

use用于将代码注入到当前模块中,而import则用于导入函数以供使用。 您可以构build一个自动导入函数的use实现,例如,当您将use Timex添加到模块时use Timex , 如果想知道我的意思 , 请查看timex.ex ,这是一个非常简单的示例build立一个可以use的模块

请参阅elixir官方入门指南中的“别名,要求和导入”页面:

 # Ensure the module is compiled and available (usually for macros) require Foo # Import functions from Foo so they can be called without the `Foo.` prefix import Foo # Invokes the custom code defined in Foo as an extension point use Foo 

要求

Elixir提供macros作为元编程的机制(编写生成代码的代码)。

macros是在编译时执行和扩展的代码块。 这意味着,为了使用macros,我们需要保证它的模块和实现在编译期间可用。 这是通过require指令完成的。

一般情况下,模块在使用前不需要使用,除非我们想要使用该模块中可用的macros。

import

我们使用import只要我们想要从其他模块轻松访问函数或macros而不使用完全限定的名称。 例如,如果我们想多次使用List模块中的duplicate/2函数,我们可以导入它:

 iex> import List, only: [duplicate: 2] List iex> duplicate :ok, 3 [:ok, :ok, :ok] 

在这种情况下,我们只从List导入函数duplicate (with arity 2)。

请注意, import模块自动require它。

使用

虽然不是一个指令,但是use是一个与require允许你在当前上下文中使用模块紧密相关的macros。 开发人员经常使用usemacros来将外部function引入当前的词汇范围,通常是模块。

在幕后, use需要给定的模块,然后调用__using__/1callback__using__/1 ,允许模块在当前上下文中注入一些代码。 一般来说,以下模块:

 defmodule Example do use Feature, option: :value end 

被编译进去

 defmodule Example do require Feature Feature.__using__(option: :value) end 

use Module 需要 Module并且还调用__using__

import ModuleModulefunction引入当前上下文 ,而不仅仅是要求它。

从Python / Java / Golang语言的背景来看, importuse对我来说也是困惑的。 这将解释代码重用机制与一些声明性语言的例子。

import

总之,在Elixir中,你不需要导入模块。 所有公共函数都可以通过完全限定的MODULE.FUNCTION语法来访问:

 iex()> Integer.mod(5, 2) 1 iex()> String.trim(" Hello Elixir ") "Hello Elixir" 

在Python / Java / Golang中,您需要先import MODULE然后才能使用该MODULE中的函数,例如Python

 In []: import math In []: math.sqrt(100) Out[]: 10.0 

那么在Elixir中import什么可能会让你大吃一惊:

我们使用导入,只要我们想要从其他模块轻松访问函数或macros而不使用完全限定的名称

https://elixir-lang.org/getting-started/alias-require-and-import.html#import

所以,如果你想inputsqrt而不是Integer.sqrttrim而不是String.trimimport将有所帮助

 iex()> import Integer Integer iex()> sqrt(100) 10.0 iex()> import String String iex()> trim(" Hello Elixir ") "Hello Elixir" 

这可能会导致阅读代码的问题,当名称冲突,所以不build议在Erlang(影响Elixir的语言)。 但Elixir没有这样的惯例,你可以自己动手使用它。

在Python中,同样的效果可以通过:

 from math import * 

并且只build议在一些特殊场景 /交互模式下使用 – 用于更短/更快的打字。

使用&要求

use / require不同的是,它们涉及到“macros” – 在Python / Java / Golang …家族中不存在的概念。

你不需要import一个模块来使用它的function,但是你需要一个模块来使用它的macros

 iex()> Integer.mod(5, 3) # mod is a function 2 iex()> Integer.is_even(42) ** (CompileError) iex:3: you must require Integer before invoking the macro Integer.is_even/1 (elixir) src/elixir_dispatch.erl:97: :elixir_dispatch.dispatch_require/6 iex()> require Integer Integer iex()> Integer.is_even(42) # is_even is a macro true 

虽然is_even可以写成一个正常的函数,但它是一个macros,因为:

在Elixir中,Integer.is_odd / 1被定义为一个macros,所以它可以用作守护进程。

https://elixir-lang.org/getting-started/alias-require-and-import.html#require

use ,摘自Elixir doc:

使用需要给定的模块,然后调用__using__/1callback,允许模块在当前上下文中注入一些代码。

 defmodule Example do use Feature, option: :value end 

被编译进去

 defmodule Example do require Feature Feature.__using__(option: :value) end 

https://elixir-lang.org/getting-started/alias-require-and-import.html#use

所以写use X和写作一样

 require X X.__using__() 

use/2 是一个macros ,macros将把代码转换为其他代码给你。

您将在下列情况下use MODULE

  • 想要访问它的macros( require
  • MODULE.__using__()执行MODULE.__using__()

在Elixir 1.5上testing