Elixir 长生不老药:使用vs导入
Elixir 长生不老药:使用vs导入,elixir,Elixir,使用和导入之间有什么区别 use是在当前上下文中使用给定模块的简单机制 从其他模块导入函数和宏 看起来有一个区别是,import让我们来选择特定的函数/宏,而use将所有内容都包含进来 还有其他区别吗?什么时候使用一个而不是另一个?use用于将代码注入当前模块,而import用于导入函数以供使用。您可以构建一个自动导入函数的use实现,例如,当您将use Timex添加到一个模块时,就像我对Timex所做的那样,这是一个非常简单的示例,说明了如何构建一个可以使用的模块 导入模块将模块的所有函数
使用
和导入
之间有什么区别
use是在当前上下文中使用给定模块的简单机制
从其他模块导入函数和宏
看起来有一个区别是,import
让我们来选择特定的函数/宏,而use
将所有内容都包含进来
还有其他区别吗?什么时候使用一个而不是另一个?
use
用于将代码注入当前模块,而import
用于导入函数以供使用。您可以构建一个自动导入函数的use
实现,例如,当您将use Timex
添加到一个模块时,就像我对Timex所做的那样,这是一个非常简单的示例,说明了如何构建一个可以使用的模块
导入模块
将模块
的所有函数和宏都带到您的模块中
需要模块
允许您使用模块
的宏,但不导入它们。(模块
的功能始终可用,且具有名称空间。)
使用模块
首先需要
模块,然后使用模块
上的宏调用\u
考虑以下几点:
defmoda-do模块
定义宏\uuuu使用\uuuu(\u选项)do
IO.puts“您正在使用ModA”
结束
def moda()do
IO.将“插入ModA”
结束
结束
defmodb-do模块
使用ModA
def modb()do
IO.puts“内置ModB”
moda()#使用模块
需要模块
,并且还使用模块上的
调用\u
导入模块
将模块
功能引入当前环境,而不仅仅是需要它。请参阅elixir官方入门指南中的页面:
#确保模块已编译且可用(通常用于宏)
需要Foo
#从Foo导入函数,以便在不使用'Foo.'前缀的情况下调用它们
进口食品
#调用Foo中定义的自定义代码作为扩展点
使用Foo
要求
Elixir提供宏作为元编程(编写生成代码的代码)的机制
宏是在编译时执行和扩展的代码块。这意味着,为了使用宏,我们需要保证其模块和实现在编译期间可用。这是通过require
指令完成的
一般来说,在使用之前不需要模块,除非我们想使用该模块中可用的宏
进口
只要我们想轻松地从其他模块访问函数或宏而不使用完全限定名,我们就使用import
。例如,如果我们想多次使用列表
模块中的duplicate/2
功能,我们可以导入它:
iex>导入列表,仅:[重复:2]
列表
iex>重复:好的,3
[:好的,:好的,:好的]
在本例中,我们仅从列表导入函数duplicate
(带arity 2)
请注意,import
ing模块自动require
s它
使用
尽管不是指令,use
是一个与require
密切相关的宏,允许您在当前上下文中使用模块。开发人员经常使用use
宏将外部功能引入当前词汇范围,通常是模块
在幕后,use
需要给定的模块,然后使用其上的\u\u\u\u\u/1
回调调用该模块,允许该模块将一些代码注入当前上下文。一般来说,以下模块:
defmodule示例do
使用功能,选项::值
结束
被编译成
defmodule Example do
require Feature
Feature.__using__(option: :value)
end
defmodule示例do
需要特性
功能。使用(选项::值)
结束
有了Python/Java/Golang语言的背景,import
vsuse
也让我感到困惑。这将用一些声明性语言示例解释代码重用机制
进口
简而言之,在Elixir中,您不需要导入模块。所有公共函数均可通过完全限定的模块访问。函数语法:
iex()> Integer.mod(5, 2)
1
iex()> String.trim(" Hello Elixir ")
"Hello Elixir"
在Python/Java/Golang中,您需要导入模块
,然后才能使用该模块中的函数,例如Python
In []: import math
In []: math.sqrt(100)
Out[]: 10.0
那么,Elixir中的import
功能可能会让您大吃一惊:
只要我们想轻松地从其他模块访问函数或宏而不使用完全限定名,我们就使用import
因此,如果您想键入sqrt
而不是Integer.sqrt
,trim
而不是String.trim
,导入将有帮助
iex()> import Integer
Integer
iex()> sqrt(100)
10.0
iex()> import String
String
iex()> trim(" Hello Elixir ")
"Hello Elixir"
这可能会导致读取代码时出现问题,并且在Erlang(影响Elixir的语言)中存在名称冲突。但在长生不老药中并没有这样的惯例,你们可以自己冒险使用
在Python中,可以通过以下方式实现相同的效果:
from math import *
而且它只建议使用/interactive模式-用于更短/更快的键入
使用和要求
use
/require
的不同之处在于,它们与“宏”相关,而“宏”是Python/Java/Golang中不存在的概念。。。家庭
您不需要导入
模块以使用其功能,但需要要求
模块使用其宏:
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
虽然甚至可以作为正常函数编写,但它是一个宏,因为:
在Elixir中,Integer.is_odd/1被定义为宏,因此可以用作保护
使用
,摘自Elixir doc:
use需要给定的模块,然后使用其上的
回调调用\u,允许模块向当前上下文中注入一些代码
defmodule Example do
require Feature
Feature.__using__(option: :value)
end
require X
X.__using__()
defmodule TextPrinter do
import IO, only: [puts: 1]
def execute(text) do
puts(text)
end
end
iex> TextPrinter.execute("Hello")
Hello
:ok
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