Elixir - 在特殊情况下不做任何事情

时间:2017-04-27 01:25:03

标签: elixir

在Elixir的case语句中,如果在case语句中满足特定条件,是否可以不执行任何操作?或者必须总是返回一些东西?

为了说明,这是我正在处理的凤凰应用程序的片段:

Enum.map(record_params, fn(record_id) ->
    record = Repo.get!(Record, record_id)
    case Repo.update(record) do
        {:ok, struct} ->
            # I DON'T REALLY NEED ANYTHING TO HAPPEN HERE... BUT I HAVE TO HAVE A CLAUSE TO MATCH WHEN THE UPDATE RETURNS {:ok, struct}
            IO.inspect struct
        {:error, changeset} ->
            errors = parse_errors(changeset)
            IO.inspect errors
            json(conn |> put_status(400), %{status: "error", message: "There was a problem updating this record.", errors: errors})
                end
end)

如果更新record,我需要知道是否有错误,获取有关它的信息,并将其返回给客户端,因此需要case语句。 ..但如果记录成功更新,我真的不需要做任何事情 - {:ok, struct}。由于这些更新是在Enum.map()内进行的,如果更新成功,我只希望地图继续循环遍历record_ids

目前,我只是将IO.inspect struct置于成功状态 - 这是无害的,但并非真的有必要。如果可能的话,我更愿意清理我的代码。由于Elixir的模式匹配,我无法移除{:ok, struct}条件,如果在这种情况下我什么都没有,我会收到错误syntax error before: '->'

现在我对Elixir(以及函数式编程范例)都是全新的,所以如果有更多的Elixirish'处理这种情况的方法,我很想听听。

4 个答案:

答案 0 :(得分:9)

尽管已经有很多答案,但我会发布另一个答案。 忽略除了一个返回之外的所有惯用的Elixir方法都是使用Kernel.SpecialForms.with/1

with {:error, changeset} <- Repo.update(record) do
  # Do whatever you want here
end

当且仅发生匹配时,将执行do块,否则将直接返回不匹配的RHO值({:ok, _}。)

要正确执行您想要的代码,请参阅@ Dogbert的答案。

答案 1 :(得分:4)

您的代码错误,因为如果有多个json错误,您可能会在同一conn上多次调用Repo.update。在这种情况下,您需要停止处理列表的其余部分。此外,由于您实际上并未检测到何时出现任何错误,因此您可能会在稍后的json上无条件地再次调用conn。如果查看日志,您应该会看到Phoenix正在多次写入相同conn的响应,例如

[debug] Processing by MyApp.PageController.index/2
  Parameters: %{}
  Pipelines: [:browser]
[info] Sent 200 in 130µs
[info] Sent 200 in 232µs
[info] Sent 200 in 498µs
[info] Sent 200 in 390µs
[info] Sent 200 in 182µs

以下是我使用Enum.reduce_while/3执行此操作的方法:

errors = Enum.reduce_while(record_params, nil, fn(record_id, nil) ->
  record = Repo.get!(Record, record_id)
  case Repo.update(record) do
    {:ok, struct} ->
      {:cont, nil}
    {:error, changeset} ->
      errors = parse_errors(changeset)
      {:halt, errors}
  end
end)

if errors do
  json(conn |> put_status(400), %{status: "error", message: "There was a problem updating this record.", errors: errors})
else
  json(conn, "no errors!")
end

答案 2 :(得分:3)

Elixir继承的Erlang约定只是使用:okIO.puts的输出

没有返回原子的分配开销,因为它们都是由运行时实现的。

答案 3 :(得分:1)

在这种特殊情况下,因为您只想为一个分支做某事,所以您可以使用if/2

{status, changeset} = Repo.update(record)
if status == :error do
  # Do whatever you want here
end

如果您需要匹配多个内容,您可能希望使用该案例并返回该分支的内容。在上面的情况下,我会返回:ok,因为操作成功了。