web-dev-qa-db-ja.com

Elixirモジュールで定数をどのように定義しますか?

Rubyでは、クラスで定数を定義している場合、それらはすべて大文字で定義します。例えば:

class MyClass
  MY_FAVORITE_NUMBER = 13
end

Elixirでこれをどのように行いますか?そのような同等物が存在しない場合、Elixirのマジックナンバーの問題をどのように回避しますか?

35
Martimatix

変数名の前に@を追加できます:

defmodule MyModule do
  @my_favorite_number 13
end

以下が docs です

44
AbM

Elixirモジュールにはメタデータを関連付けることができます。メタデータ内の各アイテムは属性と呼ばれ、その名前でアクセスされます。 @name valueを使用してモジュール内で定義します。 @nameとしてアクセスされます

defmodule Example
  @site 'StackOverflow' #defining attribute

  def get_site do
    @site #access attribute
  end 
end

これはモジュールの最上位レベルでのみ機能し、関数定義内でモジュール属性を設定することはできません。

8
coderVishal

定数を定義するもう1つの方法は、wxErlangヘッダーファイルで行った方法です。つまり、定数値を返す1行の関数を簡単に定義できます。そのようです:

  def wxHORIZONTAL, do: 4
  def wxVERTICAL, do: 8
  def wxBOTH, do: (wxHORIZONTAL ||| wxVERTICAL)

そして、同じソースコードの別の例を次に示します。

 # From "defs.h": wxDirection
  def wxLEFT, do: 16
  def wxRIGHT, do: 32
  def wxUP, do: 64
  def wxDOWN, do: 128
  def wxTOP, do: wxUP
  def wxBOTTOM, do: wxDOWN
  def wxNORTH, do: wxUP
  def wxSOUTH, do: wxDOWN
  def wxWEST, do: wxLEFT
  def wxEAST, do: wxRIGHT
  def wxALL, do: (wxUP ||| wxDOWN ||| wxRIGHT ||| wxLEFT)

ご覧のとおり、定数を別の定数の観点から定義するのが少し簡単になります。そして、これらの定数を別のモジュールに入れたいとき、私がする必要があるのはrequire WxConstantsモジュールの上部。これにより、1つの場所で定数を定義して他のいくつかの場所で使用することがはるかに簡単になります。

ちなみに、興味があればレポ here を見ることができます。

私が言うように、私は主に完全性のためにこの答えを追加します。

8

多分あなたは定数モジュールファイルを定義し、その中であなたはこのようにマクロを定義することができます

defmodule MyApp.Constants do
  defmacro const_a do
    quote do: "A"
  end
end

他のモジュールにインポートして使用します

defmodule MyApp.ModuleA do
  import MyApp.Constants

  def get_const_a do
    const_a()
  end 
end

利点は、ランタイムコストが発生しないことと、一致する場合に使用することの利点です。

case something do
  const_a() -> do_something
  _ -> do_something_else
end
4
sat

Githubを見てみると、これが使用されていることがわかります。他のモジュールから定数にアクセスできます。

ModuleA
  @my_constant 23

  defmacro my_constant, do: @my_constant


ModuleB
  Require ModuleA
  @my_constant ModuleA.my_constant

再びシンプルで魅力的なエリキシルソリューション

3
Aleksandarf

@Onorio Catenacciの答えに似ていますが、引用を使用しています。

defmodule IbGib.Constants do

  @doc """
  Use this with `use IbGib.Constants, :ib_gib`
  """
  def ib_gib do
    quote do
      defp delim, do: "^"
      defp min_id_length, do: 1
      # etc...
    end
  end

  @doc """
  Use this with `use IbGib.Constants, :error_msgs`
  """
  def error_msgs do
    quote do
      defp emsg_invalid_relations do
        "Something about the rel8ns is invalid. :/"
      end
      # etc...
    end
  end

  @doc """
  When used, dispatch to the appropriate controller/view/etc.
  """
  defmacro __using__(which) when is_atom(which) do
    apply(__MODULE__, which, [])
  end
end

そして、あなたはそれらを消費したいモジュールの上部でこのように使用します:

use IbGib.Constants, :ib_gib # < specifies only the ib_gib constants
use IbGib.Constants, :error_msgs

# ... then in some function
Logger.error emsg_invalid_relations

これは、PhoenixがMyApp.Webで句をインポート/使用する方法で得られました。私はElixirの専門家の近くにはいませんが、この方法を使用すると、必要な定数だけをインポートでき、名前空間/スコープをプレフィックスとして付ける必要はありません。この方法で、定数の個々のグループを簡単に選択できます。

ストレート関数の場合、(私は思う)それらを複数のモジュールに分割してから、モジュールをインポートする必要があるでしょう.

このモジュールと直接モジュール関数の最適化の影響はわかりませんが、特にElixirの「インポート」するさまざまな方法の練習(importusealiasrequireは、これが単一のusingまたはimportステートメントである他の言語の初心者として非常に混乱しています。

編集:定数def宣言をdefpに変更しました。これは、複数のモジュールimportが定数ファイルである場合、あいまいさが競合するためです。それらをプライベートスコープの関数に変更すると、この競合を回避できます。したがって、各モジュールには、同じ定数の独自の「プライベートコピー」があります。

1
user4275029