持续更新清单状态

时间:2018-10-14 00:37:30

标签: elixir

由于不可变性,我在弄清楚如何使用Elixir更新地图列表时遇到了一些麻烦。这是我目前的失败尝试:

import React, { Component } from "react";
import PropTypes from "prop-types";
import Comment from "./comment";
import axios from "axios";

import Article from "../screens/article";

class Comments extends Component {
  constructor(props) {
    super(props);
    this.state = {
      comments: [],

      comment: "",
      error: ""
    };

    this.load = this.load.bind(this);

    this.comment = this.comment.bind(this);
  }

  componentDidMount() {
    this.load();
  }

  load() {
    return this.props.getComments().then(comments => {
      this.setState({ comments });

      return comments;
    });
  }

  comment() {
    return this.props.submitComment().then(comment => {
      this.setState({ comment }).then(this.load);
    });
  }

  render() {

    const { comments } = this.state;

    return (
      <div>
        {comments.map(comment => (
          <Comment key={comment.id} commment={comment} />
        ))}
      </div>
    );
  }
}



export default Comments;

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 函数最多可容纳12个不同的construct_score_table/1,我想建立一个看起来像这样的地图列表:

p_score

但是我目前的尝试将其完全构建为单独的列表。我该如何不断更新现有列表,并每次都将地图附加为元素?

2 个答案:

答案 0 :(得分:1)

就像您已经提到的那样,Elixir是一种功能语言,意味着它具有不变的数据,因此您需要使用流程来管理状态。 有几种方法可以做到这一点:


使用代理的简单示例如下:

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

答案 1 :(得分:1)

  

由于不变性,我在弄清楚如何更新时遇到了一些麻烦   使用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中的列表。