Elixir结构真的是一成不变的吗?

时间:2018-11-01 19:35:19

标签: struct erlang elixir mix iex

我目前正在学习Elixir,正在阅读“ 使用Elixir,OTP和Phoenix进行功能性Web开发”,这本书对imo来说是一本好书。 在状态机一章中,我想到了以下代码:

defmodule IslandsEngine.Rules do
  alias __MODULE__

  defstruct state: :initialized

  def new(), do: %Rules{}

  def check(%Rules{state: :initialized} = rules, :add_player), do:
    {:ok, %Rules{rules | state: :players_set}}

  def check(_state, _action), do: :error

end

上面的代码应作为功能齐全的状态机工作。 我将在一些 iex 命令上方粘贴:

iex(1)> alias IslandsEngine.Rules
IslandsEngine.Rules

iex(2)> rules = Rules.new()
%IslandsEngine.Rules{state: :initialized}

iex(3)> {:ok, rules} = Rules.check(rules, :add_player)
{:ok, %IslandsEngine.Rules{state: :players_set}}

iex(4)> rules.state
:players_set

如您所见,状态结构已从:initialized更改为:add_player。很好。

我的问题是:state:结构真的是不变的吗?我的意思是,方法check/1返回带有state: :players_set语句的结构的副本,该语句遵循正确的功能模式...但是如何在不直接修改的情况下“覆盖”当前状态? / p>

非常感谢!

1 个答案:

答案 0 :(得分:4)

Elixir数据结构确实是不可变的。但是发生的是函数调用返回了一个全新的值(根据您调用的函数,该值与原始值不同)。

关于“更改变量的值”,Elixir中的that's an added feature(原始Erlang语言)。变量的值实际上并没有改变,只是重新绑定到了新值上。 Erlang VM.

自动将旧的垃圾回收

在您的示例中:

# This returns a completely new `%Rules{}` struct and rebinds
# the `rules` variable to the new term
{:ok, rules} = Rules.check(rules, :add_player)