2016-05-16 1 views
1

Tout en écrivant une fonction, je suis en utilisant la correspondance des arguments comme ceci:Regex et l'argument correspondant à la carte

def process_thing(%{} = thing) 

J'attends que thing est une carte, et est énumérable. Malheureusement, cette liste d'arguments correspond également aux expressions rationnelles spécifiées ~r/regex/, et la classe Regex (bien qu'elle renvoie true pour is_map(~r/thing/)) n'est pas Enumerable.

Comment puis-je élaborer cette définition de fonction afin que seuls Maps - ou, idéalement, les objets Enumerable - soient envoyés à cette fonction?

Répondre

5

Il n'y a aucun moyen pour de faire correspondre sur quelque chose comme Enumerable. Si vous êtes ok avec seulement des cartes, vous avez la is_map/1 fonction intégrée:

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

Une alternative est la vérification de tous les types de données que vous attendez et le soutien:

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

Si vous nécessité de soutenir tous enumerables (peut-être il sera plus facile de donner de bons conseils avec plus d'informations sur votre cas d'utilisation), vous pouvez toujours utiliser 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 

et gérer l'échec possible de Protocol.assert_impl!/2. Je ne suis pas sûr si cette implémentation est pare-balles et encore une fois, il peut y avoir une façon plus simple de mettre en œuvre cela. :)

Encore une chose: si vous voulez faire correspondre sur les cartes, mais ne correspondent pas à struct (comme Regex), une façon de le résoudre est le premier match sur les choses que vous ne voulez correspondre pour que vous les mettez à l'écart (et les manipulez comme vous le souhaitez):

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