在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'处理这种情况的方法,我很想听听。
答案 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约定只是使用:ok
和IO.puts
的输出
没有返回原子的分配开销,因为它们都是由运行时实现的。
答案 3 :(得分:1)
在这种特殊情况下,因为您只想为一个分支做某事,所以您可以使用if/2
。
{status, changeset} = Repo.update(record)
if status == :error do
# Do whatever you want here
end
如果您需要匹配多个内容,您可能希望使用该案例并返回该分支的内容。在上面的情况下,我会返回:ok
,因为操作成功了。