【发布时间】:2020-12-30 22:32:19
【问题描述】:
我正在 elixir 中开发一个 API,并且我有一个进程连续执行 6 个操作。我的问题是,如果这 6 个操作中的任何一个操作失败,我该如何中断此执行?
我不想级联成多个案例块。
其实我想要“回归”之类的东西。
有人对此有好的解决方案吗?
【问题讨论】:
-
您能出示此代码或具有代表性的等效代码吗?
标签: elixir
我正在 elixir 中开发一个 API,并且我有一个进程连续执行 6 个操作。我的问题是,如果这 6 个操作中的任何一个操作失败,我该如何中断此执行?
我不想级联成多个案例块。
其实我想要“回归”之类的东西。
有人对此有好的解决方案吗?
【问题讨论】:
标签: elixir
当 Elixir 中有一系列连续的条件(例如多个 case 块)时,with 子句(语句?运算符?)会很有用。
Elixir docs中有一个例子。
像这样比较一堆臭烘烘的嵌套 case 语句:
case op1(x) do
{:ok, result1} ->
case op2(result1) do
{:ok, result2} ->
case op3(result2) do
{:ok, result3} -> {:ok, result3}
{:error, error} -> {:error, error}
end
{:error, error} -> {:error, error}
end
{:error, error} -> {:error, error}
end
这真的很难理解,而且感觉是多余的。基本上,我们希望继续深入研究顺序操作 1、2 和 3,否则会出现错误退出。
我们可以使用with语法重写上面的内容——密切注意箭头的方向!
with {:ok, result1} <- op1(x),
{:ok, result2} <- op2(result1) do
op3(result3)
else
{:error, error} -> {:error, error}
end
您使用逗号分隔一个又一个操作,最终形成一个do 块,您可以在其中执行最终操作。
如果任何操作失败,可以将执行路由到可选的else 块中进行匹配——如果您需要区分不同的返回值(例如,如果需要特定的日志记录),这将非常有用,否则else 块是多余的,通常可以省略。
了解with 块是编写更简洁的Elixir 代码的一大步。使用 with 语法的替代方法可以是编写多个函数签名来处理每个步骤的输出,但这感觉像是很多忙碌的工作,并不总是合理的。
【讨论】:
else {:error, error} -> {:error, error} 形式的块是完全多余的。 {:error, error} 将在没有它的情况下从 with/1 返回,一旦遇到。
else 块为例很有帮助,但是,如果您确实需要匹配不同的返回值。
在长生不老药中没有返回选项真的让我有一段时间心烦意乱。我建议你拥抱模式匹配。我知道这似乎不正确,但您最终会意识到它背后的简单性。你可以不用嵌套,只需为你期望的每个模式创建一个新函数。
这是一个 sn-p,我基本上在 self() 上递归
...
def handle_cast({:get_name, port, container}, state) do
app_name = Map.get(container, "Labels") |> Map.get("app")
GenServer.cast(self(), {:domain_map, app_name, port, container})
{:noreply, state}
end
def handle_cast({:containers, containers}, state) do
Enum.map(containers, fn container ->
GenServer.cast(self(), {:container, container})
end)
{:noreply, state}
end
def handle_cast({:container, container}, state) do
Enum.map(Map.get(container, "Ports"), fn port ->
GenServer.cast(self(), {:get_name, port, container})
end)
{:noreply, state}
end
...
如果模式不匹配,那基本上就是你的 return 语句。
【讨论】: