在Ruby中,如果一个人在类中定义常量,他们会使用全部大写来定义它们。例如:
class MyClass
MY_FAVORITE_NUMBER = 13
end
你如何在Elixir中这样做?如果不存在这样的等价物,你如何解决Elixir中魔法数字的问题?
答案 0 :(得分:43)
答案 1 :(得分:7)
Elixir模块可以具有关联的元数据。元数据中的每个项称为属性,并通过其名称访问。您可以使用index.php
在模块内定义它。并以@name value
@name
记住这只适用于模块的顶层,你不能在函数定义中设置模块属性。
答案 2 :(得分:7)
定义常量的另一种方法是我使用wxErlang头文件。也就是说,您可以简单地定义一个单行函数,为您返回常量值。像这样:
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
。这样可以更容易地在一个地方定义一个常量并在其他几个地方使用它 - 对DRY有很大的帮助。
顺便说一句,如果您有好奇心,可以看到回购here。
正如我所说,为了完整起见,我补充这个答案。
答案 3 :(得分:4)
也许您定义了一个常量模块文件,在其中您可以为此定义宏
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
这样做的好处是,您不会产生任何运行时成本以及在大小写匹配时使用它的优势
{{1}}
答案 4 :(得分:2)
环顾github,我发现这很吸引我。允许从其他模块访问该常量。
ModuleA
@my_constant 23
defmacro my_constant, do: @my_constant
ModuleB
Require ModuleA
@my_constant ModuleA.my_constant
又简单又引人入胜的lix剂溶液
答案 5 :(得分:1)
我想补充一下我是如何开始做常量的,这与@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专家不远,但是使用这种方法你可以导入你想要的那些常量,你不需要在它们前面添加任何命名空间/范围。这样,您可以轻松地选择各个常量组。
使用直接函数(我认为)你必须将它们分解为多个模块,然后导入模块。
我不知道这个vs直接模块函数的优化后果,但我认为它非常整洁 - 尤其是在Elixir中导入“导入”东西的各种方法之间的练习(import
,{{1 }},use
,alias
作为来自其他语言的初学者非常混乱,这是一个require
或using
语句。
编辑:我已将常量import
声明更改为def
。这是因为当常量文件有多个模块defp
时,存在模糊性冲突。将它们更改为私有范围的函数可以避免这种冲突。因此每个模块都有自己的同一常量的“私有副本”。