【问题标题】:How can a global constant be declared in Elixir?如何在 Elixir 中声明全局常量?
【发布时间】:2021-09-16 04:41:53
【问题描述】:

Elixir 似乎是一门很棒的语言。但是声明全局常量的最佳约定是什么?

我希望模块属性可能是最合适的解决方案?

交换下面的 Horizo​​ntal_line 的定义可以修复编译错误。

defmodule ElixirTesting do

  horizontal_line = String.duplicate("-", 80)
#  def horizontal_line, do: String.duplicate("-", 80)

  def test_global_constant do
    IO.puts(horizontal_line)
    IO.puts("Console Report Section Title")
    IO.puts(horizontal_line)
    true
  end

end

【问题讨论】:

标签: elixir


【解决方案1】:

当你想到 Elixir 中的“全局常量”之类的东西时,你必须换个思路。在其他语言中,您可能会听到“一切都是对象”——在 Elixir 中,您可能会说“一切都是函数”。

实现类似“全局”的“常量”的一种简单方法是在专用模块中定义一些函数,例如

defmodule Constants do
  def pi, do: 3.14
  def timeout, 5_000
  # ... etc...
end

您可以通过Constants.piConstants.timeout 等调用轻松引用其值——或者您可以按照其他人的建议通过元编程进一步完善访问并创建宏。

正如其他人所指出的,当仅在单个模块中需要值时,模块属性是一种引入共享值的有用方法。

在许多情况下,依靠应用程序配置是建立已知基线的有用方法,因此您可以依靠不起眼的 Application.get_env/3 或更严格的 Application.fetch_env!/2 来检索“全局”-ish 值。

您可能还会发现定义环境变量以填充您的应用程序配置很有用,类似于其他语言如何水合值,例如使用像 dotenvy 这样的包,可以让您访问环境变量。

【讨论】:

  • 好点 Everett,特别是关于为此使用应用程序配置,谢谢。
【解决方案2】:

一种方法是创建一个应用级常量模块,并按照您的描述将所有全局常量放入其中。为了导出这些常量,我们需要为它们创建一个函数。例如:

defmodule App.Constants do
  @request_timeout 5000
  def get_request_timeout do
    @request_timeout
  end
end

您可以使用元编程来摆脱这些额外的功能。

defmodule Constants do
  defmacro const(const_name, const_value) do
    quote do
      def unquote(const_name)(), do: unquote(const_value)
    end
  end
end

那么……

defmodule App.Constants do
  import Constants
  
  const :request_timeout, 5000
end

App.Constants.request_timeout # you can access request timeout in your codebase like this.

【讨论】:

【解决方案3】:

如果该常量仅在该模块中使用,则模块属性是一个不错的选择。如果常量需要在模块外使用,可以声明一个同名函数,只返回模块属性。

【讨论】:

    【解决方案4】:

    这是我用于联系人的宏。

      defmacro define(name, value) do
        quote do
          defmacro unquote(name), do: unquote(value)
        end
      end
    

    请注意,您需要使用带有常量的模块,因为它们本身就是宏。

    这种方法的好处是你的常量可以在匹配中使用,甚至在守卫中。

    【讨论】:

    • 非常好!我也得试试这个。我意识到的一件事是存在绝对不会改变的内部常量(Pi,转换常量),以及可以根据运行时环境更改但在应用程序生命周期内保持不变的值,以及依赖于实时数据流的转换因子(特别是货币转换因素)。您的解决方案非常适合内部常量。
    • 既然它所做的只是defmacro,为什么还要为它创建一个新宏?
    猜你喜欢
    • 2021-10-02
    • 2020-06-27
    • 2014-10-30
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    • 2018-12-16
    相关资源
    最近更新 更多