エリクサー:使用vsインポート


134

違いは何だuseとはimport

使用は、特定のモジュールを現在のコンテキストで使用するための単純なメカニズムです。

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

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

1つの違いはimport、特定の関数/マクロを選択するのに対して、useすべてを導入することです。

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


簡単な要約: import Moduleモジュール内で使用される関数を取り込みます。 use Module使用する関数を
取り込み

回答:


213

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



エリクサーにして取得し、私はちょっとモジュールがあることについて混乱しているPythonの世界からのもの*.exのファイルとdefmoduleブロックを、そしてどのようにIEX REPLにファイルからモジュールを引くだろう
ニック・T

2
例/概念を理解しようとしています。この特定のケースでは、__using__メソッドがuse ModA?で実行されることを示しているだけです。ModBあなたが正しいものを提示した例では単にインポートを使用することはおそらく意味がありますか?
Ryan-Neal Mes 2018

35

use現在のモジュールにコードを挿入することを目的としていますが、import使用する関数をインポートするためにも使用されます。useたとえば、use Timexモジュールを追加するときにTimexで行うように、関数を自動的にインポートする実装を構築できます。意味を知りたい場合は、timex.exを参照してください。これは、することができ、モジュールuseD」


1
それで、useより一般的であると言うのは正確importですか?つまり、の機能importは次のサブセットですuse
User314159

1
import私はそれはあなたが再実装することができますと言って正確かどうかわからないよう、依然として必要であるimportuseだけではなく、それが可能だ場合、私は驚かないだろう。use絶対にもっと強力です。あなたはそれで非常に複雑なことをすることができます、例えば、私useは自分のexprotobufプロジェクトで頻繁に使用しています。モジュールをコードで拡張したり、コンパイル時にコードを実行したり、関数をモジュールに追加したりすることができます。基本的に、それimportはマクロの能力と結合します。
ビットウォーカー、2015

詳細な説明とコードへの参照に感謝します。もうわかったと思います。私はまだElixirに不慣れですが、より多くのユースケースを見ると、違いは明白になると思います。
User314159

ちょっと問題ありません。PhoenixWebフレームワークがもう1つのすばらしい場所です。Chris McCordはElixirマクロに関する本を書いており、彼はそれらをフェニックス(を含むuse)で頻繁に使用しています。ほぼ間違いなく初心者の方が読みやすくなりますがexprotobufuse限界に達してexprotobufいると思うので、どれだけ遠くまで行けるかを確認するだけでも役立つでしょう。
ビットウォーカー、2015

5
use実際にはあまり機能せず、__using__指定されたモジュールを呼び出すだけです。
Patrick Oscity 2015

25

参照してください«エイリアスを必要とし、輸入»エリクシルの公式からページスタートガイド:

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

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

14

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.sqrttrim代わりのString.trimimport意志のヘルプ

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でテスト済み


3

use Module それを必要 Moduleとし、またそれを要求__using__します。

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


0

インポート

指定されたモジュールのすべての関数とマクロを、それが呼び出されるレキシカルスコープ内でアクセスできるようにします。ほとんどの場合、インポートする必要があるのは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モジュールに挿入されています。

ちなみに、Elixirには依存関係を処理する命令がもっとあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.