首页 > 解决方案 > 有条件地附加到 Elixir 中的列表?

问题描述

在 Python 上几个月后,我正在编写 Elixir 代码,我对惯用 Elixir 的记忆很模糊。

此代码有效:

# Define workers and child supervisors to be supervised
children = [
  # Start the Ecto repository
  supervisor(Ssauction.Repo, []),
  # Start the endpoint when the application starts
  supervisor(SsauctionWeb.Endpoint, []),

  supervisor(Absinthe.Subscription, [SsauctionWeb.Endpoint]),
]

children
= if System.get_env("PERIODIC_CHECK") == "ON" do
    Enum.concat(children, [worker(Ssauction.PeriodicCheck, [])])
  else
    children
  end

但我敢肯定这很尴尬。如何用惯用的方式重写这个?

标签: listappendelixir

解决方案


您可以定义一个接受条件的辅助函数:

defp append_if(list, condition, item) do
  if condition, do: list ++ [item], else: list
end

然后像这样使用它:

[1,2,3]
|> append_if(true, 4)
|> append_if(false, 1000)

产生:

[1, 2, 3, 4]

看起来您正在使用Supervisor.Spec已弃用的模块。您可以以更现代的方式定义您的监督树,如下所示:

children =
  [
    Ssauction.Repo,
    SsauctionWeb.Endpoint,
    {Absinthe.Subscription, [SsauctionWeb.Endpoint]}
  ]
  |> append_if(System.get_env("PERIODIC_CHECK") == "ON", Ssauction.PeriodicCheck)

尽管您可能需要修改您的子主管以实施该 Supervisor行为。


如果您要构建大型列表,通常会在列表前添加,然后对结果进行一次反向操作,以避免每次都遍历整个列表:

defp prepend_if(list, condition, item) do
  if condition, do: [item | list], else: list
end

def build_list do
  []
  |> prepend_if(true, 1)
  |> prepend_if(true, 2)
  |> prepend_if(true, 3)
  |> prepend_if(false, nil)
  |> prepend_if(false, 5000)
  |> Enum.reverse()
end

推荐阅读