与条款
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
处理我们的业务流程(可能是 cond
或 if
)。这导致我们所谓的 厄运金字塔 ,因为我们必须处理可能的条件并决定:是否进一步行动。使用 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
块结果。