2016-05-16 32 views
1

在寫一個功能,我使用的參數匹配,像這樣:正則表達式和地圖參數匹配

def process_thing(%{} = thing) 

我期待那thing是一個地圖,並且可枚舉。不幸的是,這個參數列表也匹配指定爲~r/regex/的正則表達式,並且正則表達式(雖然它返回爲真is_map(~r/thing/))不是Enumerable。

我該如何創建這個函數定義,以便只有地圖或理想情況下可枚舉的東西被派發到這個函數?

回答

5

有沒有辦法匹配對某事是Enumerable。如果你確定只有地圖,那麼你有is_map/1內置功能:

def process_thing(thing) when is_map(thing) do 
    ... 
end 

一種替代方法是檢查您所期望的所有數據類型,並支持:

def process_thing(thing) when is_map(thing) or is_list(thing), do: ... 
def process_thing(%MapSet{}), do: ... 
... 

如果您需要支持所有可枚舉(也許會更容易對你的使用情況的更多信息給予很好的建議),你可以隨時使用Protocol.assert_impl!/2

def process_thing(thing) when is_map(thing) or is_list(thing), do: ... 
def process_thing(%{__struct__: struct}) do 
    assert_impl!(Enumerable, struct) 
end 

並處理Protocol.assert_impl!/2可能的失敗。我不確定這個實現是否是防彈的,並且可能有更清晰的方法來實現這一點。 :)

一兩件事:如果你想匹配在地圖上但不匹配結構(如Regex),以解決這個問題的一種方法是對事物的第一場比賽,你想要匹配,使您可以將它們擋開(然後根據需要處理它們):

def process_thing(%{__struct__: _}), do: # bad things here, we don't like structs 
def process_thing(%{} = thing), do: # hey, that's a map now!