Stream 长生不老药:顺流而下?

Stream 长生不老药:顺流而下?,stream,elixir,Stream,Elixir,我想概括一下这段代码,但看不出如何以简洁的方式做到这一点: defmodule Demo do defp side_effect(bool, label) do if bool do IO.puts label end end def go do {a,b,c} = {4,8,13} [2,3,4,5,7,8,9,10,11,12] # always in ascending order |> Stream.drop_while( fn i -

我想概括一下这段代码,但看不出如何以简洁的方式做到这一点:

defmodule Demo do

 defp side_effect(bool, label) do
   if bool do
     IO.puts label
   end
 end

 def go do
  {a,b,c} = {4,8,13}

  [2,3,4,5,7,8,9,10,11,12] # always in ascending order
  |> Stream.drop_while( fn i -> bool = (i<a); side_effect(bool, "a_#{i}"); bool end ) 
  |> Stream.drop_while( fn i -> bool = (i<b); side_effect(bool, "b_#{i}"); bool end ) 
  |> Stream.drop_while( fn i -> bool = (i<c); side_effect(bool, "c_#{i}"); bool end ) 
  |> Enum.to_list
 end
end
正如我所希望的——为输入列表中的每个元素执行一个副作用,并将一个空列表作为最终输出。 但是,是否有可能对其进行推广,以便我可以通过编程方式(基于列表)包括我喜欢的任意多行:

|> Stream.drop_while( fn i -> bool = (i<x); side_effect(bool, "x_#{i}"); bool end ) 

|>Stream.drop_while(fn i->bool=(i流是一种数据结构,这意味着您可以对其进行缩减,在每个步骤中将其细化为一组特定的值:

defmodule Demo do
  defp side_effect(var, threshold, label) do
    if var < threshold do
      IO.puts "#{label}_#{var}"
      true
    else
      false
    end
  end

  def go do
    values = [a: 4, b: 8, c: 13]

    stream =
      Enum.reduce(values, [2,3,4,5,7,8,9,10,11,12], fn {k, v}, acc ->
        Stream.drop_while(acc, fn i -> side_effect(i, v, k) end)
      end)

    Enum.to_list(stream)
  end
end
defmoduledemo-do
defp副作用(变量、阈值、标签)do
如果var<阈值do
IO.puts“#{label}#{var}”
真的
其他的
假的
结束
结束
去做什么
值=[a:4,b:8,c:13]
溪流=
枚举减少(值[2,3,4,5,7,8,9,10,11,12],fn{k,v},acc->
流.中途退出(acc,fn i->副作用(i,v,k)结束)
(完)
枚举到列表(流)
结束
结束
您还可以探索其他解决方案。例如,您可以简单地执行筛选操作,检查值是否小于列表中的阈值,而不是为值的每个部分创建流。类似如下:

defmodule Demo do
  defp side_effect(i, values) do
    pair = Enum.find(values, fn {_, v} -> i < v end)

    case pair do
      {k, v} ->
        IO.puts "#{k}_#{i}"
        false
      nil ->
        true
    end
  end

  def go do
    values = [a: 4, b: 8, c: 13]

    [2,3,4,5,7,8,9,10,11,12]
    |> Stream.filter(fn i -> side_effect(i, values) end)
    |> Enum.to_list()
  end
end
defmoduledemo-do
defp副作用(i,值)do
pair=Enum.find(值,fn{uv}->i
IO.puts“{k}{U}{i}”
假的
零->
真的
结束
结束
去做什么
值=[a:4,b:8,c:13]
[2,3,4,5,7,8,9,10,11,12]
|>流过滤器(FNI->副作用(i,值)结束)
|>枚举到_列表()
结束
结束

我不确定您是否真的需要过滤。如果不需要,Stream.map/2或Stream.each/2(仅用于副作用)会更好。

尽管第一个解决方案很漂亮,但我认为它不允许我用File.Stream(代替[2,3,4,5,7,8,9,10,11,12])开始处理这是我的计划。所以我来看看第二个解决方案。Elixir为我带来了一个全新的编程视角——它将美与理性结合在一起——非常感谢!不客气!顺便说一句,第一个解决方案也应该与File.stream一起使用。只需传递File.stream而不是列表即可减少。
defmodule Demo do
  defp side_effect(i, values) do
    pair = Enum.find(values, fn {_, v} -> i < v end)

    case pair do
      {k, v} ->
        IO.puts "#{k}_#{i}"
        false
      nil ->
        true
    end
  end

  def go do
    values = [a: 4, b: 8, c: 13]

    [2,3,4,5,7,8,9,10,11,12]
    |> Stream.filter(fn i -> side_effect(i, values) end)
    |> Enum.to_list()
  end
end