在Elixir中存储状态

时间:2017-12-07 05:37:10

标签: dictionary elixir immutability gen-server mutability

最近我解决了一个涉及更新大量键值的问题。

当然,我考虑使用 >>> arrays = [[1, 1, 2, 2], ['red', 'blue', 'red', 'blue']] >>> pd.MultiIndex.from_arrays(arrays, names=('number', 'color')) MultiIndex(levels=[[1, 2], ['blue', 'red']], labels=[[0, 0, 1, 1], [1, 0, 1, 0]], names=['number', 'color']) ,其操作类似于 String source = ae.getActionCommand(); switch (source) { case "Calculate the Area": System.out.println("Calc 1 Complete"); try { if ((Double.parseDouble(tLength.getText()) <= 0) || ((Double.parseDouble(tWidth.getText()) <= 0))) { JOptionPane.showMessageDialog(null, "invalid input, number has to be positive", "Error", JOptionPane.ERROR_MESSAGE); } else { area = Double.parseDouble(tLength.getText()) * Double.parseDouble(tWidth.getText()); } } catch (NumberFormatException e) { JOptionPane.showMessageDialog(null, "invalid input, number has to be positive", "Error", JOptionPane.ERROR_MESSAGE); } break; case "Calculate the Cost": System.out.println("Calc 2 Complete"); if (flrType.equals("Wood")) { cost = area * 20; } else if (flrType.equals("Carpet")) { cost = area * 10; } break;

然而,考虑到Elixir中数据结构的不可变性,这似乎是不够的:

Map

然后我通过在Map.put/3中保持iex> m = Map.put(%{}, :a, 1) %{a: 1} iex> Map.put(m, :b, 2) %{a: 1, b: 2} iex> m %{a: 1} 的状态并使用Map来电更新来解决问题。

一般来说,这是正确的做法,还是这个太多了?

2 个答案:

答案 0 :(得分:8)

  

然后我通过在GenServer [...]中保持m = Map.put(%{}, :a, 1) #⇒ %{a: 1} m = Map.put(m, :b, 2) #⇒ %{a: 1, b: 2} 的状态来解决问题   一般来说,这是正确的方法,还是这个太多了?

这在很大程度上取决于你的目标。 存储州的方式有很多种。重新绑定变量,如:

m

存储任何内容。它将局部变量GenServer绑定到RHO,并且一旦控制流离开范围,该变量就会变为垃圾收集。无论您是否需要在单一范围内使用上述地图,GenServer(和其他州持有者)都是一种过度杀伤。

OTOH,如果您需要长时间存储状态并在不同范围之间共享(例如,在不同进程之间),GenServer是实现这一目标的最简单方法。在Elixir中,我们有Agent模块来减少用作简单内存存储的GenServer的样板,但我的建议是始终使用Agent:迟早{{ 1}}对你的目的来说太紧了。

此外,可以使用ets模块来保留进程内共享的内存中键值存储。

dets是一种在进程重启之间存储状态的方法。

最后,mnesia是一种OTP本机方法,用于在重新启动和不同节点之间共享状态 (在分布式环境中)。

答案 1 :(得分:2)

你的第一种方法是对的,你只是犯了一件事。

您应该在更新地图时重新绑定变量,例如:

iex> m = Map.put(%{}, :a, 1)
%{a: 1}
iex> m = Map.put(m, :b, 2)
%{a: 1, b: 2}
iex> m
%{a: 1, b: 2}

但是你必须要知道它并没有改变变量,它会创建一个新的地图并将其重新绑定到同一个变量。

现在,这种方法是最简单的方法,您必须将此映射传递给使用它的每个函数。作为替代方案,您可以考虑使用Agent模块。所有信息的内容及其用途均可在其文档中找到。