2017-12-02 10 views
1

ストリームから要素を取る:与えられた引数では条件付きで、私は次の関数実装しました

def gaussian(center, height, width) do 
    Stream.iterate(1, &(&1 + 1)) 
    |> Stream.map(fn (x) -> x - center end) 
    |> Stream.map(fn (x) -> :math.pow(x, 2) end) 
    |> Stream.map(fn (x) -> -x/(2 * :math.pow(width, 2)) end) 
    |> Stream.map(fn (x) -> height * :math.exp(x) end) 
    |> Stream.map(&Kernel.round/1) 
    |> Stream.take_while(&(&1 > 0)) 
    |> Enum.to_list                
    end 

を、空のリストが返されます。

iex> gaussian(10, 10, 3) 
[] 

Stream.take_while/2

def gaussian(center, height, width) do 
    Stream.iterate(1, &(&1 + 1)) 
    |> Stream.map(fn (x) -> x - center end) 
    |> Stream.map(fn (x) -> :math.pow(x, 2) end) 
    |> Stream.map(fn (x) -> -x/(2 * :math.pow(width, 2)) end) 
    |> Stream.map(fn (x) -> height * :math.exp(x) end) 
    |> Stream.map(&Kernel.round/1) 
    #|> Stream.take_while(&(&1 > 0))             
    #|> Enum.to_list                 
    |> Enum.take(20) 
    end 
を削除します

ただし、これは:

iex> gaussian(10, 10, 3) 
[0, 0, 1, 1, 2, 4, 6, 8, 9, 10, 9, 8, 6, 4, 2, 1, 1, 0, 0, 0] 

私のStream.take_while/2コールに何か問題がありますか、ここで何かが欠落していますか?

答えて

2

Stream.take_while/2評価する関数が最初に出現したときの評価は、falseになりません。あなたのケースでは

、中にあなたの機能:最初の反復で

gaussian(10, 10, 3) 

などの指定された引数で

|> Stream.take_while(&(&1 > 0)) 

0は、このように、それはあなたの表現&1 > 0falseと評価されて、さらに反復していない受信します。

あなたのような何かにあなたのコードを展開する場合は、自分でいることを確認することができます。

|> Stream.take_while(fn (x) -> IO.inspect(x); x > 0 end) 

たぶん、そのStream.filter/2あなたが使用したいですか?

あなたの問題を解決するのに役立ちます。

+0

「IO.inspect/1」は本当に役に立ちます。「Stream.filter/2」は無限ストリームで操作しようとしているようですので、完了しません。 – category

+1

@categoryどのような完了条件ですか? 1つはありますか?あるいは、あなたの他の例のように最初の '20'要素だけを取りたいと思っていますか?次に、 '|> Enum.to_list'を' |> Enum.take(20) 'に置き換える必要があります。終了条件が指定されていない場合、無限に評価できるストリームの性質です。 –

+0

+1は 'Stream.with_index/2'でそれを使用して完了条件を述べるために、中心の後の偏差の数を検査する条件を定義することができました。 – category

関連する問題