在实例化新结构时使用“|”

Using `|` when instantiating a new struct

以下代码是从 Manning 发布的 '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

我不明白在创建新的 TodoList 时在 add 函数末尾使用 todo_list |。我尝试完全删除它,但看不出结果有什么不同。任何人都可以向我解释它正在实现什么吗?

这是更新地图的shorthand语法:

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

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

请注意,与 Map.put/3, you can only update existing keys, which gives you some safety. It behaves more like Erlang's :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 函数可能不再按预期工作,丢弃其他键。所以我建议你把它留在那里。