違いは何だuseとはimport?
使用は、特定のモジュールを現在のコンテキストで使用するための単純なメカニズムです。
https://hexdocs.pm/elixir/Kernel.SpecialForms.html#import/2
他のモジュールから関数とマクロをインポートします
1つの違いはimport、特定の関数/マクロを選択するのに対して、useすべてを導入することです。
他に違いはありますか?いつどちらを使用しますか?
違いは何だuseとはimport?
使用は、特定のモジュールを現在のコンテキストで使用するための単純なメカニズムです。
https://hexdocs.pm/elixir/Kernel.SpecialForms.html#import/2
他のモジュールから関数とマクロをインポートします
1つの違いはimport、特定の関数/マクロを選択するのに対して、useすべてを導入することです。
他に違いはありますか?いつどちらを使用しますか?
回答:
import ModuleModule名前空間のないすべての関数とマクロをモジュールに取り込みます。
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
used ModAと同様にimport、に挿入されるステートメントを生成しましたModB。
*.exのファイルとdefmoduleブロックを、そしてどのようにIEX REPLにファイルからモジュールを引くだろう
__using__メソッドがuse ModA?で実行されることを示しているだけです。ModBあなたが正しいものを提示した例では単にインポートを使用することはおそらく意味がありますか?
use現在のモジュールにコードを挿入することを目的としていますが、import使用する関数をインポートするためにも使用されます。useたとえば、use Timexモジュールを追加するときにTimexで行うように、関数を自動的にインポートする実装を構築できます。意味を知りたい場合は、timex.exを参照してください。これは、することができ、モジュールuseD」
useより一般的であると言うのは正確importですか?つまり、の機能importは次のサブセットですuse
import私はそれはあなたが再実装することができますと言って正確かどうかわからないよう、依然として必要であるimportとuseだけではなく、それが可能だ場合、私は驚かないだろう。use絶対にもっと強力です。あなたはそれで非常に複雑なことをすることができます、例えば、私useは自分のexprotobufプロジェクトで頻繁に使用しています。モジュールをコードで拡張したり、コンパイル時にコードを実行したり、関数をモジュールに追加したりすることができます。基本的に、それimportはマクロの能力と結合します。
use)で頻繁に使用しています。ほぼ間違いなく初心者の方が読みやすくなりますがexprotobuf、use限界に達してexprotobufいると思うので、どれだけ遠くまで行けるかを確認するだけでも役立つでしょう。
use実際にはあまり機能せず、__using__指定されたモジュールを呼び出すだけです。
参照してください«エイリアスを必要とし、輸入»エリクシルの公式からページスタートガイド:
# 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(アリティ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言語からの背景により、importvs 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に影響を与える言語)では推奨されません。しかし、エリクサーにはそのような慣習はありません。自分のリスクでそれを使用できます。
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からの抜粋:
使用するには、指定されたモジュールが必要であり、そのモジュールの
__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でテスト済み
指定されたモジュールのすべての関数とマクロを、それが呼び出されるレキシカルスコープ内でアクセスできるようにします。ほとんどの場合、インポートする必要があるのは1つ以上の関数/マクロのみであることに注意してください。
例:
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使用する関数を