use
和之间有什么区别import
?
use是在当前上下文中使用给定模块的简单机制
https://hexdocs.pm/elixir/Kernel.SpecialForms.html#import/2
从其他模块导入函数和宏
看起来有一个区别是import
让您选择特定的功能/宏,同时use
将所有内容都带入其中。
还有其他区别吗?您什么时候可以使用另一个?
use
和之间有什么区别import
?
use是在当前上下文中使用给定模块的简单机制
https://hexdocs.pm/elixir/Kernel.SpecialForms.html#import/2
从其他模块导入函数和宏
看起来有一个区别是import
让您选择特定的功能/宏,同时use
将所有内容都带入其中。
还有其他区别吗?您什么时候可以使用另一个?
Answers:
import Module
将所有Module
未命名空间的函数和宏引入模块。
require Module
允许您使用的宏,Module
但不能导入它们。(的功能Module
始终可用命名空间。)
use Module
第一个requires
模块,然后在__using__
宏上调用Module
。
考虑以下:
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
它会生成一个import
插入到中的语句ModB
。
*.ex
文件和defmodule
块)以及如何将模块从文件中拉入iex REPL感到困惑
__using__
方法是在use ModA
?上执行的。ModB
在您提供的示例中正确使用import可能会有意义?
use
用于将代码注入当前模块,同时import
又用于导入要使用的功能。use
例如,您可以构建一个实现自动导入功能的实现,就像我在添加use Timex
模块时使用Timex 一样,如果您想了解我的意思,请查看timex.ex,这是一个如何构建a的非常简单的示例可以使用use
的模块
use
比一般更准确import
吗?也就是说,的功能import
是use
import
仍然是必要的,因为我不知道,如果它是准确的说,你可以重新实现import
与use
孤独,但如果可能的话,我不会感到惊讶。use
虽然绝对更强大。您可以用它来做非常复杂的事情,例如,我use
在我的exprotobuf
项目中大量使用了它,您可以检查是否要查看它是否达到了极限。您可以使用代码扩展模块,在编译时执行代码,向模块添加功能等。基本上,它结合import
了宏的功能。
use
)中大量使用它们。对于初学者来说exprotobuf
,阅读use
本书几乎绝对比阅读起来容易,但是我想我可能exprotobuf
会把它推到极限,因此,看看您能走多远,也许很有用。
use
实际上并没有做什么,它只是调用__using__
指定的模块。
请参阅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提供宏作为元编程的一种机制(编写生成代码的代码)。
宏是在编译时执行和扩展的代码块。这意味着,为了使用宏,我们需要确保其模块和实现在编译期间可用。这是通过require
指令完成的。
通常,除非我们要使用该模块中可用的宏,否则在使用之前不需要模块。
我们使用import
每当我们想要轻松访问功能或者其他模块宏而不使用完全合格的名称。例如,如果我们想多次使用模块中的duplicate/2
函数List
,可以将其导入:
iex> import List, only: [duplicate: 2]
List
iex> duplicate :ok, 3
[:ok, :ok, :ok]
在这种情况下,我们仅从中导入函数duplicate
(具有arity 2)List
。
请注意,import
自动为模块添加模块require
。
尽管不是指令,但use
与require
它紧密相关的宏使您可以在当前上下文中使用模块。use
开发人员经常使用该宏将外部功能引入当前的词法范围(通常是模块)。
在幕后,use
需要给定的模块,然后__using__/1
在其上调用回调,以允许该模块向当前上下文中注入一些代码。一般来说,以下模块:
defmodule Example do
use Feature, option: :value
end
被编译成
defmodule Example do
require Feature
Feature.__using__(option: :value)
end
凭借Python / Java / Golang语言的背景,import
vs use
也让我感到困惑。这将通过一些声明性语言示例说明代码重用机制。
简而言之,在Elixir中,您不需要导入模块。可以使用完全限定的MODULE.FUNCTION语法访问所有公共函数:
iex()> Integer.mod(5, 2)
1
iex()> String.trim(" Hello Elixir ")
"Hello Elixir"
在Python / Java / Golang中,您需要import MODULE
先使用该模块中的函数,例如Python
In []: import math
In []: math.sqrt(100)
Out[]: 10.0
然后import
,Elixir的作用可能会让您感到惊讶:
每当我们想轻松访问其他模块中的函数或宏而无需使用完全限定的名称时,我们都会使用import
https://elixir-lang.org/getting-started/alias-require-and-import.html#import
因此,如果您想输入sqrt
而不是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"
这可能会导致阅读代码以及出现名称冲突时出现问题,因此不建议在Erlang(影响Elixir的语言)中使用。但是Elixir中没有这样的约定,您可以自行承担风险。
在Python中,可以通过以下方式实现相同的效果:
from math import *
并且仅建议在某些特殊情况 /交互模式下使用-以缩短/加快打字速度。
是什么让use
/ require
不同的是,它们涉及到“微距” -这个概念并不在Python / Java的/ Golang ......家庭存在。
您不需要import
模块即可使用其功能,但需要require
模块即可使用其宏:
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
可以写为普通函数,但它是一个宏,因为:
在Elixir中,将Integer.is_odd / 1定义为宏,以便可以将其用作防护。
https://elixir-lang.org/getting-started/alias-require-and-import.html#require
use
,摘录自Elixir doc:
use需要给定的模块,然后
__using__/1
在其上调用回调,以允许该模块向当前上下文中注入一些代码。
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
是一个宏,宏会为您将代码转换为其他代码。
您将要在use MODULE
何时:
require
)MODULE.__using__()
在Elixir 1.5上测试
使给定模块中的所有函数和宏都可以在调用它的词法范围内访问。请记住,在大多数情况下,只需要导入一个或多个功能/宏即可。
例:
defmodule TextPrinter do
import IO, only: [puts: 1]
def execute(text) do
puts(text)
end
end
iex> TextPrinter.execute("Hello")
Hello
:ok
这个宏允许您在当前模块中注入任何代码。与一起使用外部库时use
,请务必小心,因为您可能不确定幕后到底发生了什么。
例:
defmodule Printer do
defmacro __using__(_opts) do
quote do
def execute(text) do
IO.puts(text)
end
end
end
end
defmodule TextPrinter do
use Printer
end
iex> TextPrinter.execute("Hello")
Hello
:ok
里面的场景代码__using__
已经被注入到TextPrinter
模块中。
import Module
引入要在模块内部使用的功能。use Module
引入要使用的函数并将其公开公开在您的模块上