假设我有一个函数 main_function
这取决于其他三个函数的结果,每个函数都可以返回 {:ok, result}
或 {:error, error}
.如何避免在 javascript 中感觉像回调 hell 的深度嵌套的 case 语句。
例子:
def func1(input) do
case SOMECONDITION do
{:ok, result} ->
{:ok, result}
{:error, error} ->
{:error, error}
end
end
def func2(input) do
case SOMECONDITION do
{:ok, result} ->
{:ok, result}
{:error, error} ->
{:error, error}
end
end
def func3(input) do
case SOMECONDITION do
{:ok, result} ->
{:ok, result}
{:error, error} ->
{:error, error}
end
end
def main_function(input) do
case func1(input) do
{:ok, result} ->
case func2(result) do
{:ok, result} ->
case func3(result) do
{:ok, result} ->
{:ok, EXPECTED_OUTCOME}
{:error, error} ->
{:error, error}
end
{:error, error} ->
{:error, error}
end
{:error, error} ->
{:error, error}
end
end
end
只是感觉不太对...
最佳答案
[编辑]:我为涵盖此概念的精彩演讲添加了一个便捷链接,以及下面 ElixirConf 2018 中更复杂需求的解决方案。
别担心 - Elixir 可以满足您的需求。你想要this special form : with/1
with/1
当且仅当它们与预期结果匹配时,才会继续执行函数。
你的主要功能基本上看起来像:
def main_function(input) do
with {:ok, result_1} <- func1(input),
{:ok, result_2} <- func2(result_1),
...,
do: {:ok, EXPECTED_OUTCOME}
end
当它找不到匹配项时,说因为有一个像
{:error, _error}
这样的元组特殊形式将返回遇到的第一个错误并停止执行函数。您还可以添加一个 else 条件。我使用这个的一个例子是,当用户可能期望一些需要完成很多功能的操作时,我想提醒他们同样的事情,不管它在哪里失败:
def main_function(input) do
with {:ok, result_1} <- func1(input),
{:ok, result_2} <- func2(result_1),
... do
{:ok, EXPECTED_OUTCOME}
else
_error ->
{:error, "Couldn't complete action"}
end
end
其他资源:
这是 Credo 的作者关于这个概念的精彩演讲,由 ElixirConf 2018 提供:https://www.youtube.com/watch?v=ycpNi701aCs&t=473s
这是一篇关于
with/1
的精彩帖子: https://www.erlang-solutions.com/blog/exploring-with-the-elixir-special-form.html
关于Elixir:如何避免深度嵌套的 case 语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50827551/