如何构建函数以便我不会发生冲突?

时间:2017-09-04 22:04:51

标签: elixir

例如,我想要一个可以这样调用的函数:

foo :bar, key: "value" do
  "some block value"
end

foo key: "value" do
  "some block value"
end

foo :bar do
  "some block value"
end

或只是

foo key: "value"

首先,函数定义如下所示:

def foo(bar, opts \\ [], [do: block])

我需要适应的情况下,我只是传递选项而不是:bar,我得到编译错误。我完全理解为什么(opts \\ []创建了更多与我的其他函数定义相匹配的函数)。那么,在某种程度上允许foo方法工作的良好解决方法是什么?

1 个答案:

答案 0 :(得分:4)

我将各种可能性定义为单独的arity函数,它使用3个值调用一个do_foo/3函数。假设bar永远不是一个列表(如果它可以是一个列表,那么对于arity 1和2来说整个事情就变得模棱两可了,因为我们无法知道该值是针对bar还是{{1}你可以做类似的事情:

opts

输出:

defmodule A do
  def foo(opts) when is_list(opts), do: do_foo(nil, opts, nil)
  def foo(bar), do: do_foo(bar, nil, nil)
  def foo(opts, [do: block]) when is_list(opts), do: do_foo(nil, opts, block)
  def foo(bar, [do: block]), do: do_foo(bar, nil, block)
  def foo(bar, opts, [do: block]), do: do_foo(bar, opts, block)

  defp do_foo(bar, opts, block) do
    IO.inspect {bar, opts, block}
  end
end

A.foo :bar, key: "value" do
  "some block value"
end

A.foo key: "value" do
  "some block value"
end

A.foo :bar do
  "some block value"
end

A.foo key: "value"