为什么 if 语句中的模式匹配不受欢迎?

Why is pattern matching in an if statement frowned upon?

我刚刚在我的 Phoenix 应用程序中安装了 Credo 混合库,它告诉我 web/views/error_helpers.ex 文件在错误标记方法中有一个重构机会:

def error_tag(form, field) do
  if error = form.errors[field] do
    content_tag :span, translate_error(error), class: "help-block"
  end
end

Credo 给出的信息是:

There should be no matches in if conditions.

换句话说 if error = form.errors[field] do 中有模式匹配。但是,除了该消息之外,Credo 库没有详细说明。

为什么这么糟糕?

这并没有那么糟糕,但通常 if 表达式不那么地道。 casecond 之类的替代方案更强大,可以更明确地说明发生的事情,并可以导致更可预测的行为。可能有一些情况(比如这个)这段代码没问题,我不知道与其他情况相比分析这种情况会有多容易。这个表达式,例如,returns nil 当没有错误时......这并不像处理 2 个案例和提供空字符串那样明确。

就像其他张贴者所说的那样,它不那么惯用,可能会导致一些分析问题(或常见的错误,例如输入 = 而不是 ==)。我对此的主要论点是以下情况:

if get_status = :ok do 
  # Some code
else
  # Some other code

这是非常有限的,而且表达能力不强,使用 cond do 您可以执行以下操作:

cond get_status do
  :ok -> # Some code
  :not_ok -> # Some other code
  _ -> # More code
end

如果条件几乎是二元的,你要么得到 A,要么得到其他东西。如果结果是本地函数调用或类似的布尔值,这很好,但如果你在分布式系统上工作,从另一台机器或类似的机器获取信息,cond do 更强大、简洁并帮助你推理并为意外行为设置代码(上面代码中的下划线,if get_status 是一个获取特定服务状态的函数,我们期望类似 :ok 的服务准备就绪和 :not_ok 如果服务没有准备好,那么如果服务的机器挂了怎么办?或者我们的网线断开了?)。

当然这可以通过多个 if 语句来实现,但这会导致糟糕的代码可读性或可维护性不佳。