我发现虽然 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/