struct - Elixir 结构真的不可变吗?
问题描述
我目前正在学习 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
语句的结构的副本,该语句遵循正确的功能模式......但是它如何“覆盖”当前状态而不直接修改它?
非常感谢!
解决方案
Elixir 数据结构确实是不可变的。但是发生的情况是函数调用返回一个全新的值(这与原始值不同,具体取决于您调用的函数)。
至于“更改变量的值”,这是(在原始语言上)的一个附加功能。变量的值实际上并没有改变,它只是重新绑定到新的值。旧的会自动被垃圾回收Elixir
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)
推荐阅读
- node.js - NodeJS - 强大的 200 MB 文件限制和崩溃
- android - Android studio ics-openVPN搭建问题
- machine-learning - 自定义词汇表上的 Sklearn Countvectorizer
- html - 将 2 个元素放在同一行
- ms-access - Currentdb.Execute (Database.Execute) 不工作或抛出错误
- python-2.7 - Python遍历日期的txt文件并更改日期格式
- ios - 按年月日排序时的问题
- c# - Visual Studio + Docker - 使用编辑并继续调试应用程序?
- javascript - Chrome JavaScript 的通用串行接口库
- html - Angular 6:根据活动选项卡更改 div 的背景颜色