解决带有“ with”表达式的_only_问题的建议-访问成功结果

问题描述

考虑以下代码

with {:a,first_result} <- {:a,List.first(["apple"])},{:b,b} <- {:b,%{} |> to_string} do
  {:ok,"happy path"}
else
  {:a,_} -> {:error,"this will never be a problem"}
  {:b,error} -> {:error,"Why can I not print #{first_result} here?"}
end

我通过反复试验得知,此代码返回

{:error,"Why can I not print apple here?"}
正如我最初对这种语法所期望的那样。相反,编译器告诉我first_result块中未定义else。这是有道理的,因为“子句链”返回失败子句的错误结果。

所以我有2个问题:

  1. 达到预期结果的最佳方法是什么?我应该只使用两个单独的case表达式吗?
  2. 想象一下,如果第一子句使用Repo.insert数据库添加了一些内容。 Ecto是否知道它在with表达式中并在提交事务之前等待所有子句成功执行? :thinking:这似乎不太可能。那么,为什么这个表达式不允许我们访问任何成功的结果?

在使用with时似乎应该非常小心,因为如果我理解正确(我可能不太理解),那么我将获得“部分成功”,而看不到成功的结果。

欢迎任何建议和见识!我希望问题清楚。

P.S。我已经读过https://hexdocs.pm/elixir/Kernel.SpecialForms.html#with/1。它只是说“链条被终止”。

解决方法

我在这里回答了我的问题:

https://elixirforum.com/t/advice-for-working-around-my-only-problem-with-with-expressions-accessing-success-results/33720/6

向Bluejay用户提供道具。

用他们的话说,“这有效”:

    with {:a,first_result} <- {:a,List.first(["apple"])},{:b,first_result,:something} <- {:b,:other_thing} do
      {:ok,"happy path"}
    else
      {:a,_} -> {:error,"this will never be a problem"}
      {:b,"Now I can print #{first_result} here"}
    end

所以答案是使用先前子句结果中的变量来扩展要匹配的子句元组。