剥离/检查的惯用方法 :ok 和管道第二个 arg

use*_*431 0 elixir

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

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

File.cwd()
|> IO.puts()
Run Code Online (Sandbox Code Playgroud)

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

{:ok, ret} = File.cwd()
IO.puts(ret)
Run Code Online (Sandbox Code Playgroud)

Ale*_*kin 5

没有惯用的方法来管理第二个 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)
Run Code Online (Sandbox Code Playgroud)

这样你要么输出c 要么返回第一个不匹配(读取:错误)的结果。

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

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

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