药剂:使用vs导入
use
和import
什么区别?
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 Module
将import Module
所有function和macros取消为您的模块。
require Module
允许您使用Module
macros,但不导入它们。 ( Module
function始终可用名称空间。)
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
它会生成一个插入ModB
的import
语句。
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。 开发人员经常使用use
macros来将外部function引入当前的词汇范围,通常是模块。
在幕后, use
需要给定的模块,然后调用__using__/1
callback__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 Module
将Module
function引入当前上下文 ,而不仅仅是要求它。
从Python / Java / Golang语言的背景来看, import
和use
对我来说也是困惑的。 这将解释代码重用机制与一些声明性语言的例子。
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.sqrt
, trim
而不是String.trim
, import
将有所帮助
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__/1
callback,允许模块在当前上下文中注入一些代码。
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