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

vpt*_*ron 4 elixir

以下代码是由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
Run Code Online (Sandbox Code Playgroud)

我不明白在创建新函数时todo_list |add函数末尾的用法TodoList.我尝试完全删除它,但结果并没有真正区别.任何人都可以向我解释它的成就吗?

Pat*_*ity 8

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

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

iex> map = %{map | foo: "quux"}
%{foo: "quux"}
Run Code Online (Sandbox Code Playgroud)

请注意,与之不同的是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
Run Code Online (Sandbox Code Playgroud)

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

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