2015-06-26 8 views
4

Следующий код скопирован из «Эликсир в действии», опубликованный Manning.Использование `|` при создании новой структуры

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. Я попытался полностью удалить его и не мог увидеть разницу в результате. Может ли кто-нибудь объяснить мне, чего он добивается?

ответ

8

Это сокращенная синтаксис для обновления карты:

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

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

Обратите внимание, что в отличие от Map.put/3, вы можете обновить только существующие ключи, которые дает вам некоторую безопасность. Он ведет себя как 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 может работать не так, как ожидалось, отбрасывая другие ключи. Поэтому я рекомендую вам оставить его там.

Смежные вопросы