在实例化新结构时使用`|`

时间:2015-06-26 13:03:38

标签: elixir

以下代码是从' Elixir in Action'中复制粘贴的。曼宁出版。

defmodule TodoList do

  defstruct auto_id: 1, entries: HashDict.new

  def new, do: %TodoList{}

  def add(
    %TodoList{entries: entries, auto_id: auto_id} = todo_list,
    entry) do
      entry = Map.put(entry, :id, auto_id)
      new_entries = HashDict.put(entries, auto_id, entry)
      %TodoList{ todo_list |
        entries: new_entries,
        auto_id: auto_id + 1
      }
    end

end

我不了解在创建新todo_list |时在add函数末尾使用TodoList。我尝试完全删除它,但结果并没有真正看出差异。任何人都可以向我解释它的成就吗?

1 个答案:

答案 0 :(得分:8)

这是更新地图的简写语法:

iex> map = %{foo: "bar"}
%{foo: "bar"}

iex> map = %{map | foo: "quux"}
%{foo: "quux"}

请注意,与Map.put/3不同,您只能更新现有密钥,这样可以提供一些安全保障。它的行为更像Erlang的:maps.update/3

iex> map = %{map | baz: "quux"}
** (ArgumentError) argument error
    (stdlib) :maps.update(:baz, "quux", %{foo: "bar"})
    (stdlib) erl_eval.erl:255: anonymous fn/2 in :erl_eval.expr/5
    (stdlib) lists.erl:1261: :lists.foldl/3

另请注意,像%TodoList{}这样的结构实际上只是地图,因此所有结构都与结构完全相同。

现在,因为您正在设置结构的所有有效键,所以现在是否将todo_list |放在那里没有区别。但是,如果向结构中添加了新密钥,则add函数可能无法正常工作,丢弃其他密钥。所以我建议你把它放在那里。