有没有办法直接从Elixir中的元组返回值?

时间:2018-07-19 15:24:55

标签: elixir

给出一个返回一个元组的函数,有没有办法从同一行中的那个元组中选择并返回一个特定的值?我经常发现自己在Elixir中使用了这种模式,并且想知道是否有捷径可以达到相同的结果。

例如,我在下面的函数中选择并返回result

def foo() do
  {:ok, result} = get_result()
  result
end

有没有办法消除该方法中第二行代码的需要?

3 个答案:

答案 0 :(得分:7)

您可以使用elem/2来获取术语的第二项:

def foo() do
  get_result() |> elem(1)
end

,但这不会断定元组的第一个元素是:ok,就像您的原始代码一样。如果还想断言,则可以定义和重用一个简单的函数:

def foo do
  get_result() |> extract()
end

def extract({:ok, term}), do: term
def extract(_), do: :error # raise an error here if you want

答案 1 :(得分:5)

典型的处理方法是使用Kernel.SpecialForms.with/1

def foo(), do: with {:ok, result} <- get_result(), do: result

这种方法除了简洁明了的符号外,还具有许多优点。它将通过{em>传播:error(以及与{:ok, _}不匹配的任何事物),从而使错误处理成为一种魅力。

是否要舍弃任何不好的输入并仅返回:error,请在else中使用with子句:

def foo(), do: with {:ok, result} <- get_result(), do: result, else: (_ -> :error)

要模仿初始代码的 exact 行为(不正常时提高MatchError):

def foo(), do: with {:ok, result} <- get_result(), do: result, else: (42 = :error)

答案 2 :(得分:1)

您可以在一行中对其进行编码:

def foo, do: get_result |> (&(elem(&1,0) == :ok && elem(&1,1) || :error)).()

有关此处使用的几种语法糖的更多详细信息:
  • one line中编写函数
  • 将第一个函数的结果流化为第二个函数的第一个参数:fun1() |> fun2()
  • 使用以下语法使用一个参数创建一个匿名函数: (&()).()
  • 模拟三元条件:

    A && B || Cif A do B else C end

这是在长生不老药中编码高尔夫的一种好方法。但是,您会失去可读性。