简体   繁体   中英

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.

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:

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. 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.


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
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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