Jaka jest różnica między use
i import
?
use to prosty mechanizm wykorzystania danego modułu w aktualnym kontekście
https://hexdocs.pm/elixir/Kernel.SpecialForms.html#import/2
Importuje funkcje i makra z innych modułów
Wygląda na to, że jedna różnica polega import
na tym, że możesz wybrać określone funkcje / makra, a jednocześnie use
wprowadzić wszystko.
Czy są inne różnice? Kiedy użyłbyś jednego nad drugim?
import Module
zawiera funkcje do wykorzystania w module.use Module
wprowadza funkcje do użycia ORAZ ujawnia je publicznie w Twoim moduleOdpowiedzi:
import Module
wprowadzaModule
do modułu wszystkie funkcje i makra z przestrzeni bez nazw.require Module
umożliwia korzystanie z makr programu,Module
ale ich nie importuje. (FunkcjeModule
są zawsze dostępne w przestrzeni nazw).use Module
pierwszyrequires
moduł, a następnie wywołuje__using__
makroModule
.Rozważ następujące:
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
Nie zostanie to skompilowane, ponieważ
ModA.moda()
nie zostało zaimportowane do programuModB
.Jednak skompilowane zostaną następujące elementy:
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
Jak wtedy, gdy
use
byłybyModA
to wygenerowałimport
komunikatu, który został wstawionyModB
.źródło
*.ex
plikami idefmodule
blokami oraz w jaki sposób wyciągnąłbyś moduł z pliku do REPL iex__using__
metoda jest wykonywana nause ModA
? Prawdopodobnie miałoby sens po prostu użycie importuModB
w przedstawionym przykładzie, prawda?use
jest przeznaczony do wstrzykiwania kodu do bieżącego modułu, podczas gdyimport
służy do importowania funkcji do użycia. Możesz zbudowaćuse
implementację, która automatycznie importuje funkcje, na przykład tak, jak robię to z Timex, kiedy dodajeszuse Timex
do modułu, spójrz na timex.ex, jeśli chcesz wiedzieć, co mam na myśli , to bardzo prosty przykład, jak zbudować moduł, który może byćuse
'dźródło
use
jest bardziej ogólne niżimport
? Oznacza to, że funkcjonalnośćimport
jest podzbioremuse
import
nadal jest konieczne, ponieważ nie wiem, czy jest to dokładne powiedzieć można reimplementimport
zuse
samodzielnie, ale nie zdziw się, jeśli to możliwe.use
jest jednak absolutnie potężniejszy. Możesz z nim robić bardzo złożone rzeczy, na przykład ja intensywnie wykorzystuję jeuse
w moimexprotobuf
projekcie, które możesz sprawdzić, jeśli chcesz zobaczyć, jak przesuwa się do granic możliwości. Możesz rozszerzać moduły o kod, wykonywać kod w czasie kompilacji, dodawać funkcje do modułu itp. Zasadniczo łączy toimport
i moc makr.use
). Prawie na pewno będzie łatwiejsze do przeczytania dla początkującego niżexprotobuf
, ale myślę, że prawdopodobnie dążęuse
do jego granic,exprotobuf
więc może być przydatne po prostu zobaczyć, jak daleko możesz to znieść.use
w rzeczywistości niewiele robi, po prostu wywołuje__using__
określony moduł.Zobacz stronę „alias, require i import” w oficjalnym przewodniku wprowadzającym do elixiru:
# 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
Wymagać
Elixir dostarcza makra jako mechanizm do metaprogramowania (pisania kodu, który generuje kod).
Makra to fragmenty kodu, które są wykonywane i rozwijane w czasie kompilacji. Oznacza to, że aby korzystać z makra, musimy zagwarantować, że jego moduł i implementacja będą dostępne podczas kompilacji. Odbywa się to za pomocą
require
dyrektywy.Ogólnie moduł nie musi być wymagany przed użyciem, chyba że chcemy użyć makr dostępnych w tym module.
Import
Używamy
import
zawsze, gdy chcemy mieć łatwy dostęp do funkcji lub makr z innych modułów bez używania w pełni kwalifikowanej nazwy. Przykładowo, jeśli chcemy kilkakrotnie skorzystać zduplicate/2
funkcji zList
modułu, możemy ją zaimportować:iex> import List, only: [duplicate: 2] List iex> duplicate :ok, 3 [:ok, :ok, :ok]
W tym przypadku importujemy tylko funkcję
duplicate
(z liczbą 2) zList
.Zwróć uwagę, że
import
moduł automatycznierequire
go obsługuje.Posługiwać się
Chociaż nie jest to dyrektywa,
use
jest ściśle powiązanym makrem,require
które pozwala na użycie modułu w bieżącym kontekście.use
Makro jest często wykorzystywany przez programistów przynieść funkcjonalność zewnętrznego do bieżącego zakresu leksykalnego, często modułów.W tle
use
wymaga danego modułu, a następnie wywołuje__using__/1
wywołanie zwrotne umożliwiające modułowi wstrzyknięcie kodu do bieżącego kontekstu. Ogólnie rzecz biorąc, następujący moduł:defmodule Example do use Feature, option: :value end
jest wkompilowany w
defmodule Example do require Feature Feature.__using__(option: :value) end
źródło
Mając tło z języków Python / Java / Golang,
import
vsuse
był dla mnie zdezorientowany. To wyjaśni mechanizm ponownego użycia kodu z kilkoma przykładami języków deklaratywnych.import
Krótko mówiąc, w Elixirze nie musisz importować modułów. Dostęp do wszystkich funkcji publicznych można uzyskać poprzez w pełni kwalifikowany MODUŁ. Składnia FUNKCJI:
W Python / Java / Golang musisz to zrobić
import MODULE
zanim będziesz mógł używać funkcji w tym MODULE, np. PythonW takim razie to, co
import
robi Elixir, może Cię zaskoczyć:https://elixir-lang.org/getting-started/alias-require-and-import.html#import
Więc jeśli chcesz pisać
sqrt
zamiastInteger.sqrt
,trim
zamiastString.trim
,import
pomożeMoże to powodować problemy z czytaniem kodu i konfliktami nazw, więc nie jest to zalecane w Erlangu (języku, który ma wpływ na Elixir). Ale w Elixirze nie ma takiej konwencji, możesz z niej korzystać na własne ryzyko.
W Pythonie ten sam efekt można osiągnąć poprzez:
i zaleca się używać go tylko w niektórych specjalnych scenariuszach / trybie interaktywnym - do krótszego / szybszego pisania.
użyj i wymagaj
Co sprawia,
use
/require
inna jest to, że odnoszą się one do „makro” - pojęcie, które nie istnieje w Python / Java / Golang ... rodziny.Nie potrzebujesz
import
modułu, aby korzystać z jego funkcji, ale potrzebujeszrequire
modułu, aby używać jego makr :Chociaż
is_even
można go zapisać jako normalną funkcję, jest to makro, ponieważ:https://elixir-lang.org/getting-started/alias-require-and-import.html#require
use
, fragment z dokumentu Elixir:jest wkompilowany w
https://elixir-lang.org/getting-started/alias-require-and-import.html#use
Więc pisanie
use X
jest tym samym, co pisanieuse/2
jest makrem , makro przekształci kod na inny kod za Ciebie.Będziesz chciał,
use MODULE
gdy:require
)MODULE.__using__()
Testowane na Elixirze 1.5
źródło
use Module
wymaga,Module
a także wzywa__using__
.import Module
wprowadzaModule
funkcjonalność w aktualny kontekst , a nie tylko jej wymaga.źródło
Import
Udostępnia wszystkie funkcje i makra z danego modułu w zakresie leksykalnym, w którym jest wywoływany. Należy pamiętać, że w większości przypadków do zaimportowania wystarczy jedna lub więcej funkcji / makr.
Przykład:
Posługiwać się
To makro umożliwia wstrzyknięcie dowolnego kodu w bieżącym module. Należy zachować ostrożność podczas korzystania z bibliotek zewnętrznych
use
, ponieważ możesz nie być pewien, co dokładnie dzieje się za kulisami.Przykład:
Znajdujący się za sceną kod
__using__
został wstrzyknięty doTextPrinter
modułu.Nawiasem mówiąc, w Elixirze jest więcej instrukcji obsługi zależności .
źródło