关于使用“with”表达式解决我_only_问题的建议 - 访问成功结果

Advice for working around my _only_ problem with “with” expressions - accessing success results

考虑这段代码:

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

我通过反复试验得知此代码 不会 return

{:error, "Why can I not print apple here?"}

正如我最初对这种语法的预期。相反,编译器告诉我 first_result 没有在 else 块中定义。这是有道理的,因为“子句链”return是失败子句的错误结果。

所以我有两个问题:

  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, first_result, :other_thing} do
      {:ok, "happy path"}
    else
      {:a, _} -> {:error, "this will never be a problem"}
      {:b, first_result, _} -> {:error, "Now I can print #{first_result} here"}
    end

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