Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Elixir:如何避免深入嵌套的case语句?_Elixir - Fatal编程技术网

Elixir:如何避免深入嵌套的case语句?

Elixir:如何避免深入嵌套的case语句?,elixir,Elixir,假设我有一个函数main_function,它依赖于其他三个函数的结果,每个函数可以返回{:ok,result}或{:error,error}。我怎样才能避免在javascript中有像回调地狱一样的深度嵌套的case语句呢 例如: def func1(input) do case SOMECONDITION do {:ok, result} -> {:ok, result} {:error, error} -> {:error, erro

假设我有一个函数
main_function
,它依赖于其他三个函数的结果,每个函数可以返回
{:ok,result}
{:error,error}
。我怎样才能避免在javascript中有像回调地狱一样的深度嵌套的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

这感觉不太对劲…

[Edit]:我在一篇精彩的演讲中添加了一个方便的链接,介绍了这一概念,以及下面ElixirConf 2018针对更复杂需求的解决方案。

别担心,长生不老药已经覆盖了你。您需要:
和/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
额外资源: 以下是《信条》作者关于这一概念的精彩演讲,由ElixirConf 2018提供:


下面是一篇关于
的很棒的帖子,其中有/1

回答了对公认答案的评论:


这是一个有趣的方法。但是假设
func1
func2
正在向数据库写入数据。如果
func1
返回错误,我根本不希望执行
func2
。会是这样吗

如果您使用的是exto,还有另一个选项

假设
func1
func2
func3
都写入数据库,但步骤在
func2
处失败,这意味着
func1
已经写入数据库

假设它们返回
{:ok,result}
{:error,error}

救命啊

alias-exto.Multi
别名MyApp.Repo
def主功能(输入)do
结果=
Multi.new()
|>Multi.run(:result1,fn\u1->func1(输入)结束)
|>Multi.run(:result2和func2(&1.result1))
|>Multi.run(:result3和func3(&1.result2))
|>回购交易()
案例结果如何
{:好,%{result1:u,result2:u,result3:}}->
{:好的,预期结果}
{:error,error,{u changes}->
{:错误,错误}
结束
结束

对于Multi,返回错误元组将中止任何进一步的操作,并使整个Multi失败。另外,由于它使用的是事务,任何成功的都将回滚。

我认为您可以使用
语句。这是一个有趣的方法。但是假设
func1
func2
正在向数据库写入数据。如果
func1
返回错误,我根本不希望执行
func2
。会是这样吗?这样就可以了!它在第一次不匹配时停止执行,因此在这种情况下,第一个错误-因此如果func1不成功,func2将不会尝试执行。不要忘记
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