2017-09-04 69 views
1

例如,我想有一個可以這樣調用函數:如何構造函數以免發生衝突?

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]) 

的時刻,我需要適應的情況下,我傳遞的選擇,但不是:酒吧,我得到編譯錯誤。我完全理解爲什麼(opts \\ []創建更多符合我的其他函數定義的函數)。那麼,有什麼方法可以使foo方法起作用?

回答

4

我會將各種可能性定義爲單獨的arity函數,這些函數用3個值調用一個do_foo/3函數。假設bar從來都不是一個列表(如果可以這樣整個事情就變得曖昧元數1和2的列表,因爲我們無法知道該值是否爲baropts),你可以這樣做:

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" 

輸出:

{:bar, [key: "value"], "some block value"} 
{nil, [key: "value"], "some block value"} 
{:bar, nil, "some block value"} 
{nil, [key: "value"], nil} 
+0

啊,太棒了。沒有考慮製作次要的非模糊功能。謝謝! – Grocery

相關問題