2016-08-21 12 views
2

一連の値の組み合わせに対していくつかの分析を実行したいと思います。理解のスコープの問題

私は、以下の機能を持っていますが、何らかの理由で、内包が完了した後、それは各反復

の理解の内側ではありませんしながら、関数本体の終わりに、変数 analyticsは、まだ空のリストです

アイデア?

def handle_cast({:start}, state) do 
    intervals = [7, 30, 90] 
    groupings = ["day_of_week", "time_of_day"] 
    aggregators = [ 
     %{ 
     domain: "support", 
     metric: "new_conversations", 
     func: &App.get_new_conversations/2 
     }, 
     %{ 
     domain: "support", 
     metric: "closed_conversations", 
     func: &App.get_closed_conversations/2 
     }, 
     %{ 
     domain: "support", 
     metric: "median_response_time", 
     func: &App.get_median_response_time/2 
     }, 
    ] 

    Repo.transaction(fn -> 
     Repo.delete_all(Analytic) 

     analytics = [] 
     for interval <- intervals do 
     for grouping <- groupings do 
      for %{domain: domain, metric: metric, func: func} <- aggregators do 
      analytic = 
       func.(grouping, interval) 
       |> Enum.map(fn %{"app_id" => app_id, "data" => data} = result -> 
       %Analytic{app_id: app_id, domain: domain, metric: metric, grouping: grouping, interval_in_days: interval, data: data} 
       end) 

      analytics = [analytic|analytics] 
      end 
     end 
     end 
    end) 

    {:noreply, state} 
    end 

答えて

3

エリクサーの変数は不変ですが再バインド可能です。つまり、analytics = [analytic|analytics]という行が新しいリストを作成し、そのブロックのスコープについてanalyticsという変数にバインドしているということです。ブロックが終了すると、変更はforの次の反復で保持されません。例:あなたが書いたコードの場合

iex(1)> x = 1 
1 
iex(2)> for i <- 1..3 do 
...(2)> IO.puts(x); x = x + i; IO.puts(x) 
...(2)> end 
1 
2 
1 
3 
1 
4 

、あなたはforはその中の最後の式の値のリストを返すという事実を使用することができますし、analyticsに最も外側forの戻り値を格納しますが、ちょっとした問題があります:ネストされたリストで終わるでしょう:

iex(1)> for i <- 1..2 do 
...(1)> for j <- 1..2 do 
...(1)>  for k <- 1..2 do 
...(1)>  {i, j, k} 
...(1)>  end 
...(1)> end 
...(1)> end 
[[[{1, 1, 1}, {1, 1, 2}], [{1, 2, 1}, {1, 2, 2}]], 
[[{2, 1, 1}, {2, 1, 2}], [{2, 2, 1}, {2, 2, 2}]]] 

しかし、単純な解決策があります。 forは、単一の呼び出しで複数の<-条項を受け入れ、自動的にフラットなリストを返します。このメソッドを使用して

iex(1)> for i <- 1..2, j <- 1..2, k <- 1..2 do 
...(1)> {i, j, k} 
...(1)> end 
[{1, 1, 1}, {1, 1, 2}, {1, 2, 1}, {1, 2, 2}, {2, 1, 1}, {2, 1, 2}, {2, 2, 1}, 
{2, 2, 2}] 

を、あなたのコードは次のようになります。

analytics = 
    for interval <- intervals, 
     grouping <- groupings, 
     %{domain: domain, metric: metric, func: func} <- aggregators do 
     func.(grouping, interval) 
     |> Enum.map(fn %{"app_id" => app_id, "data" => data} = result -> 
     %Analytic{app_id: app_id, domain: domain, metric: metric, grouping: grouping, interval_in_days: interval, data: data} 
     end) 
    end 
    end 
end 

これは、あなたが最も可能性の高い期待していた同じ出力を与える必要があります元のコードから。

+0

パーフェクト、ありがとうございました! – Tarlen