Имея опыт работы с языками 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, может вас удивить:
Мы используем импорт всякий раз, когда хотим легко получить доступ к функциям или макросам из других модулей без использования полного имени.
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:
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
import Module
вводит функции, которые будут использоваться внутри вашего модуля.use Module
вводит функции для использования И публикует их в вашем модуле