Com experiência nas linguagens Python / Java / Golang, o import
vs use
também foi confuso para mim. Isso explicará o mecanismo de reutilização de código com alguns exemplos de linguagens declarativas.
importar
Em resumo, no Elixir, você não precisa importar módulos. Todas as funções públicas podem ser acessadas pela sintaxe MODULE.FUNCTION totalmente qualificada:
iex()> Integer.mod(5, 2)
1
iex()> String.trim(" Hello Elixir ")
"Hello Elixir"
Em Python / Java / Golang, você precisa import MODULE
antes de poder usar funções nesse MODULE, por exemplo, Python
In []: import math
In []: math.sqrt(100)
Out[]: 10.0
Então, o que o import
Elixir faz pode surpreendê-lo:
Utilizamos a importação sempre que queremos acessar facilmente funções ou macros de outros módulos sem usar o nome completo.
https://elixir-lang.org/getting-started/alias-require-and-import.html#import
Então, se você quiser digitar em sqrt
vez de Integer.sqrt
, em trim
vez de String.trim
, import
ajudará
iex()> import Integer
Integer
iex()> sqrt(100)
10.0
iex()> import String
String
iex()> trim(" Hello Elixir ")
"Hello Elixir"
Isso pode causar problemas na leitura do código e, quando houver conflito de nome, não é recomendado no Erlang (o idioma que influencia o Elixir). Mas não existe essa convenção no Elixir, você pode usá-lo por sua conta e risco.
No Python, o mesmo efeito pode ser feito por:
from math import *
e recomenda-se usar apenas em alguns cenários especiais / modo interativo - para digitação mais curta / mais rápida.
use e exija
O que faz use
/ require
diferente é que eles se relacionam com "macro" - o conceito que não existe na família Python / Java / Golang ....
Você não precisa de import
um módulo para usar suas funções, mas precisa de require
um módulo para usar suas 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
Embora is_even
possa ser escrita como uma função normal, é uma macro porque:
No Elixir, Integer.is_odd / 1 é definido como uma macro para que possa ser usado como uma proteção.
https://elixir-lang.org/getting-started/alias-require-and-import.html#require
use
, para extrair do Elixir doc:
use requer o módulo fornecido e, em seguida, chama o __using__/1
retorno de chamada, permitindo que o módulo injete algum código no contexto atual.
defmodule Example do
use Feature, option: :value
end
é compilado em
defmodule Example do
require Feature
Feature.__using__(option: :value)
end
https://elixir-lang.org/getting-started/alias-require-and-import.html#use
Então escrever use X
é o mesmo que escrever
require X
X.__using__()
use/2
é uma macro , a macro transformará o código em outro código para você.
Você vai querer use MODULE
quando você:
- quer acessar suas macros (
require
)
- E executar
MODULE.__using__()
Testado em Elixir 1.5
import Module
traz funções para serem usadas dentro do seu módulo.use Module
traz em funções a serem utilizados e os expõe publicamente seu módulo