与条款

with 子句用于组合匹配子句。看起来我们将匿名函数或处理函数与多个实体(匹配子句)结合起来。考虑这种情况:我们创建一个用户,将其插入数据库,然后创建问候电子邮件,然后将其发送给用户。

如果没有 with 子句,我们可能会写这样的东西(我省略了函数实现):

case create_user(user_params) do
  {:ok, user} ->
    case Mailer.compose_email(user) do
      {:ok, email} ->
        Mailer.send_email(email)
      {:error, reason} ->
        handle_error
    end
  {:error, changeset} ->
    handle_error
end

在这里,我们使用 case 处理我们的业务流程(可能是 condif)。这导致我们所谓的 厄运金字塔 ,因为我们必须处理可能的条件并决定:是否进一步行动。使用 with 语句重写此代码会更好:

with {:ok, user} <- create_user(user_params),
     {:ok, email} <- Mailer.compose_email(user) do
  {:ok, Mailer.send_email}
else
  {:error, _reason} ->
    handle_error
end

在上面的代码片段中,我们用 with 重写了嵌套的 case 子句。在 with 中,我们调用一些函数(匿名或命名)和输出上的模式匹配。如果全部匹配,则 with 返回 do 块结果,否则为 else 块结果。

我们可以省略 else,因此 with 将返回 do 块结果或第一个失败结果。

所以,with 语句的值是它的 do 块结果。