首页 > 解决方案 > 剥离/检查的惯用方法:ok 和管道第二个 arg

问题描述

我喜欢管道,Elixir 喜欢管道,但返回 {:ok, actual_return_value} 似乎也很常见。有没有用管道处理这个的成语?

我现在正在学习“Programming Elixir”,下面的练习解决方案可能是可能的,但不完整。

File.cwd()
|> IO.puts()

我不是在寻找这个解决方案:

{:ok, ret} = File.cwd()
IO.puts(ret)

标签: elixir

解决方案


没有惯用的方法来管道第二个 arg。

不鼓励在两种情况下使用管道:

  • 链条中只有两个环节
  • 链中的下一个函数接受前一个函数的结果而不是作为第一个参数,或者结果提供的东西与链中的下一个函数所期望的不同。

只要有意义,核心库就会尽最大努力提供所有的糖来让管道变得有魅力。考虑调整字符串。我们有两个replace/4函数:具有几乎相似的功能但前者将字符串作为第一个参数,以便在字符串出现时更容易通过管道进入链,而后者接受正则表达式作为第一个参数。String.replace/4 Regex.replace/4

如果您发现自己对如何使用管道感到困惑——这是一个明确的信号,您不应该使用管道。很简单,语言本身暗示了最好的方法。事实上,没有人{:ok, value}从总是成功的函数中返回。也就是说,可能还有其他结果。在问题的情况下,{:error, reason}。让我猜猜:你不希望你的代码在它上面炸毁。善意地提醒你。当然,你仍然可以使用 管道Kernel.elem/2,但你真的想要吗?我打赌没有。

至少有两种不同的方法,具体取决于您实际想要实现的目标。

一种是使用 monadic SpecialForms.with/1,它要么继续执行子句,要么返回第一个不匹配的结果。

with {:ok, a} <- Mod.fun1(),
     {:ok, b} <- Mod.fun2(a),
     {:ok, c} <- Mod.fun3(b),
  do: IO.puts(c)

这样,您可以输出c 返回第一个不匹配(读取:错误)的结果。

另一种方法是使用Kernel.SpecialForms.case/2.

File.cwd()
|> case do
  {:ok, result} -> result
  {:error, reason} -> LOG_OR_SOMETHING
end

选择您的任何选择,但请记住:管道应该在它所属的地方使用,而不是在任何地方使用。


推荐阅读