Постоянно обновлять состояние списка - PullRequest
0 голосов
/ 14 октября 2018

Из-за неизменности у меня возникли проблемы с выяснением, как обновить список карт с помощью Elixir.Вот моя текущая неудачная попытка:

defp score_table_map(question, team) do
  prediction_score = Enum.find(team.prediction_scores, &(&1.question_id == question.id))
  construct_score_table(p_score)
end

defp construct_score_table(p_score) do
  information_map = []
  information_map = information_map ++ [%{team_score: p_score.score, team_id: p_score.team_id}]
end

Эта construct_score_table/1 функция принимает до 12 различных p_score, и я хочу создать список карт, который выглядит следующим образом:

[ 
  %{team_score: p_score.score, team_id: p_score.team_id},
  %{team_score: p_score.score, team_id: p_score.team_id},
  %{team_score: p_score.score, team_id: p_score.team_id},
  %{team_score: p_score.score, team_id: p_score.team_id},
]

Но моя нынешняя попытка строит его как отдельные списки.Как я могу постоянно обновлять существующий список и каждый раз добавлять карту как элемент?

Ответы [ 2 ]

0 голосов
/ 14 октября 2018

Из-за неизменности у меня возникли проблемы с выяснением того, как обновить список карт с помощью Elixir.

На функциональных языках вы передаете данные в функции, а функции преобразуютсяданные и вернуть его.Итак, самый простой способ сделать то, что вы хотите, это передать список карт в вашу функцию вместе с pscore.Затем функция может вернуть новый список карт.Вот пример:

defmodule PScore do
  defstruct score: 0, team_id: 0
end

defmodule My do

  def update_pscores(list_of_maps, p_score) do
    [%{team_score: p_score.score, team_id: p_score.team_id} | list_of_maps]
  end

  def go do
    pscore = %PScore{score: 3, team_id: 1}
    pscores = update_pscores([], pscore)
    pscore = %PScore{score: 4, team_id: 2}
    pscores = update_pscores(pscores, pscore)
    IO.puts(inspect pscores)
  end

end

My.go

Компиляция в iex:

> c "my.exs"       
warning: redefining module PScore (current version defined in memory)
  my.exs:1

warning: redefining module My (current version defined in memory)
  my.exs:5

[%{team_id: 2, team_score: 4}, %{team_id: 1, team_score: 3}] 
[My, PScore]

Если вы хотите сохранить карты Pscore в том же порядке, в котором они были добавлены в список, вы можете Enum.reverse() список, возвращаемый update_pscores().

Вам определенно не нужно создавать другой процесс, например, Агент или GenServer, для обновления списка в Elixir.

0 голосов
/ 14 октября 2018

Как вы уже упоминали, Elixir - это функциональный язык, означающий, что он содержит неизменяемые данные, поэтому вам нужны процессы для управления состоянием. Есть несколько способов сделать это:

  • Чтение / запись данных из ETS Таблицы

  • Используйте простое Agent

  • Или используйте GenServer


Простой пример использования агента будет выглядеть следующим образом:

defmodule ScoreTable do
  use Agent

  def start_link do
    Agent.start_link(fn -> [] end, name: __MODULE__)
  end

  def get_all_scores do
    Agent.get(__MODULE__, &(&1))
  end

  def add_score(score) do
    Agent.update(__MODULE__, &(&1 ++ [score]))
  end
end

Теперь просто запустите агент ScoreTable, как только приложение запустится, и вы сможете прочитать/ написать состояние списка результатов:

# Add a score
ScoreTable.add_score(team_score_map)

# Get all scores back
ScoreTable.get_all_scores
...