web-dev-qa-db-ja.com

Elixir:使用vsインポート

useimportの違いは何ですか?

useは、指定されたモジュールを現在のコンテキストに使用するためのシンプルなメカニズムです

https://hexdocs.pm/elixir/Kernel.SpecialForms.html#import/2

他のモジュールから関数とマクロをインポートします

1つの違いはimportのように見えますが、useはすべてを取り込むのに対して、特定の関数/マクロを選択できます。

他に違いはありますか?いつ他を使用しますか?

120
User314159

_import Module_は、Moduleのすべての関数とマクロを名前空間なしでモジュールに取り込みます。

_require Module_では、Moduleのマクロを使用できますが、インポートはしません。 (Moduleの関数は常に名前空間付きで利用可能です。)

_use Module_最初にrequiresモジュールを実行し、Moduleで___using___マクロを呼び出します。

以下を考慮してください。

_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ステートメントを生成しました。

183
greggreg

useは現在のモジュールにコードを挿入するためのもので、importは使用する関数をインポートするために使用されます。たとえば、Timexでモジュールにuse Timexを追加するときと同様に、関数を自動的にインポートするuse実装を構築できます 。timexを見てください。 ex私が何を意味するのか知りたい場合 、それはuse 'dになり得るモジュールを構築する方法の非常に簡単な例です

29
bitwalker

"alias、require、and import" エリクサーの公式スタートガイドのページをご覧ください:

# 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を使用します。たとえば、Listモジュールのduplicate/2関数を数回使用する場合、インポートできます。

iex> import List, only: [duplicate: 2]
List
iex> duplicate :ok, 3
[:ok, :ok, :ok]

この場合、duplicateから関数List(アリティ2)のみをインポートしています。

モジュールを自動的にimporting requiresすることに注意してください。

つかいます

ディレクティブではありませんが、userequireと密接に関連するマクロであり、現在のコンテキストでモジュールを使用できます。 useマクロは、開発者が外部機能を現在の字句スコープ(多くの場合モジュール)に取り込むために頻繁に使用されます。

舞台裏では、useは指定されたモジュールを必要とし、そのモジュールで__using__/1コールバックを呼び出して、モジュールが現在のコンテキストにコードを挿入できるようにします。一般的に、次のモジュール:

defmodule Example do
  use Feature, option: :value
end

にコンパイルされます

defmodule Example do
  require Feature
  Feature.__using__(option: :value)
end
18
fetsh

Python/Java/Golang言語のバックグラウンドで、importuseも混乱していました。これは、いくつかの宣言型言語の例でコード再利用メカニズムを説明します。

インポート

つまり、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
_

それから、Elixirのimportはあなたを驚かせるかもしれません:

完全修飾名を使用せずに、他のモジュールから関数またはマクロに簡単にアクセスする場合は常にインポートを使用します

https://elixir-lang.org/getting-started/alias-require-and-import.html#import

したがって、_Integer.sqrt_の代わりにsqrtと入力したい場合、_String.trim_の代わりに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 docからの抜粋:

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
  • AND MODULE.__using__()を実行します

Elixir 1.5でテスト済み

11
HVNSweeting

use ModulerequiresModuleまた、その上で__using__を呼び出します。

import Moduleは、必要なだけでなく、Module機能を現在のコンテキストにもたらします。

3
hagi-tragger