简体   繁体   English

有条件地附加到 Elixir 中的列表?

[英]Conditionally appending to a list in Elixir?

I'm working on Elixir code after a few months on Python, and my memory of idiomatic Elixir is fuzzy.在 Python 上几个月后,我正在研究 Elixir 代码,而我的 memory 的惯用 ZA12EB062ECA60378 是模糊的。

This code works:此代码有效:

# 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

But I'm sure it's awkward.但我敢肯定这很尴尬。 How would one rewrite this idiomatically?如何用惯用的方式重写这个?

You can define a helper function that accepts a conditional:您可以定义一个接受条件的助手 function:

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

And then use it like this:然后像这样使用它:

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

Produces:生产:

[1, 2, 3, 4]

It looks like you are using the Supervisor.Spec module, which is deprecated.看起来您正在使用已弃用的Supervisor.Spec模块。 You can define your supervision tree in a more modern way something like this:您可以以更现代的方式定义您的监督树,如下所示:

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

Although you'll probably need to modify your child supervisors to implement the Supervisor behaviour.尽管您可能需要修改您的子主管以实施Supervisor行为。


If you are going to build up large lists, it's common to prepend to the list and then do a single reverse of the results, to avoid appeding which traverses the whole list each time:如果您要构建大型列表,通常会在列表前添加,然后对结果进行一次反向操作,以避免每次都遍历整个列表:

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

You could also do;你也可以这样做;

[
  supervisor(Ssauction.Repo, []),
  supervisor(SsauctionWeb.Endpoint, []),
  supervisor(Absinthe.Subscription, [SsauctionWeb.Endpoint]),
]
|> Kernel.++(if System.get_env("PERIODIC_CHECK") == "ON" do
   [worker(Ssauction.PeriodicCheck, [])]
  else
   []
  end
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM