Rubyでは、クラスで定数を定義している場合、それらはすべて大文字で定義します。例えば:
class MyClass
MY_FAVORITE_NUMBER = 13
end
Elixirでこれをどのように行いますか?そのような同等物が存在しない場合、Elixirのマジックナンバーの問題をどのように回避しますか?
Elixirモジュールにはメタデータを関連付けることができます。メタデータ内の各アイテムは属性と呼ばれ、その名前でアクセスされます。 @name value
を使用してモジュール内で定義します。 @name
としてアクセスされます
defmodule Example
@site 'StackOverflow' #defining attribute
def get_site do
@site #access attribute
end
end
これはモジュールの最上位レベルでのみ機能し、関数定義内でモジュール属性を設定することはできません。
定数を定義するもう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 を見ることができます。
私が言うように、私は主に完全性のためにこの答えを追加します。
多分あなたは定数モジュールファイルを定義し、その中であなたはこのようにマクロを定義することができます
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
Githubを見てみると、これが使用されていることがわかります。他のモジュールから定数にアクセスできます。
ModuleA
@my_constant 23
defmacro my_constant, do: @my_constant
ModuleB
Require ModuleA
@my_constant ModuleA.my_constant
再びシンプルで魅力的なエリキシルソリューション
@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の「インポート」するさまざまな方法の練習(import
、use
、 alias
、require
は、これが単一のusing
またはimport
ステートメントである他の言語の初心者として非常に混乱しています。
編集:定数def
宣言をdefp
に変更しました。これは、複数のモジュールimport
が定数ファイルである場合、あいまいさが競合するためです。それらをプライベートスコープの関数に変更すると、この競合を回避できます。したがって、各モジュールには、同じ定数の独自の「プライベートコピー」があります。