elixir - 在 Elixir 中,有没有办法使 _real_ 常量?

标签 elixir constraints constants immutability reusability

我发现虽然 Elixir 拥有不变性,但这种不变性隐藏在可变抽象层之间,这有点误导和混淆。

例如,

如果我有代码:

foo = {:cat, "Puff"}
bar = foo
foo = {:cat, "Pepper"}

我可以期待酒吧保持{:cat, "Puff"}但是 foo 不断变化的值可能会让人难以推理。

当我第一次阅读模块属性时,我认为它们会提供一些解决方案,但有人向我指出这是完全有效的代码:
defmodule Cats do
   @cat "Puff"
   def foo, do: @cat

   @cat "Pepper"
   def bar, do: @cat
end

是否可以依赖保持不变的函数定义?例如。
defmodule Cats do
   def foo, do: "Puff"
   def bar, do: "Pepper"
end

这样的代码可以被认为是惯用的吗?
有什么理由我不应该这样做吗?

是否有任何其他类型的实体我可以声明为具有某种值(value),而没有任何其他代码为该实体赋予新值(value)的可能性?

最佳答案

我想你回答了你自己的问题。我的理解是使用模块属性作为常量是标准做法,并且是 even recommended in the getting started guide ,但正如您所指出的,模块属性可以在编译期间重新绑定(bind)。如果您真的想要保证“如果我使用一个标记的实体,结果将始终是相同的”,那么正如您所指出的,定义函数可以保证这一点。

尽管即使使用函数,也可以声明另一个返回不同值的子句:

defmodule Cats do
  def foo, do: "Puff"
  def foo("not Puff"), do: "Piggles"
end

如果您不想声明很多函数,则可以声明一个返回定义值映射的函数。

defmodule Cats do
  def names, do: %{foo: "Puff", bar: "Piffles"}
end

然后像这样使用它:

iex(1)> Cats.names.foo
"Puff"
iex(2)> Cats.names.bar
"Piffles"

或同一功能的多个子句:

defmodule Cats do
  def names(:foo), do: "Puff"
  def names(:bar), do: "Piffles"
end

iex(1)> Cats.names(:foo)
"Puff"
iex(2)> Cats.names(:bar)
"Piffles"

关于elixir - 在 Elixir 中,有没有办法使 _real_ 常量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57444737/

相关文章:

elixir - 什么时候应该在 .exs 文件中使用 defmodule

mysql - 删除所有表后恢复数据库时,InnoDB 提示外键名称正在使用

java - java中的HTTP和HTTPS默认端口号常量

c++ - static const 对命名空间成员有什么影响

elixir - 通过添加可选参数 elixir 实现函数 def 冲突

elixir - 如何别名在mix.exs中运行两次?

elixir - __using__ 内嵌套 use 语句的别名

swift - 使用 MFMessageComposeViewController、MFMailComposeViewController 后约束(?)发生了变化

jpa - 不区分大小写的 JPA 唯一约束?

c# - 如何使用 const int 属性的名称