2017-12-02 223 views
1

我已經實現了以下功能:有條件採取元素從Stream

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的第一次出現的評價。

在你的情況下,你在功能:

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

與指定的參數等

gaussian(10, 10, 3) 

在第一次迭代中接收0因而它不進一步迭代作爲表達&1 > 0的計算結果爲false

您可以檢查自己,如果你的代碼擴展到類似:

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

也許它Stream.filter/2你想使用?

希望幫助您解決您的問題!

+0

謝謝'IO.inspect/1'確實有幫助 - 'Stream.filter/2'似乎嘗試和無限流的操作,所以不會完成。 – category

+1

@category然後完成條件是什麼?有一個嗎?或者,也許你想只採取像你的另一個例子中的第一個'20'元素?然後你需要用'|> Enum.take(20)'替換'|> Enum.to_list'。如果沒有指定終止條件,這是他們可以評估無限大小的流的性質。 –

+0

+1提的完成條件 - 使用與'Stream.with_index/2',我設法定義條件,該中心經過檢查偏差數。 – category