2016-07-06 12 views
11

Nie mogę znaleźć sposobu dopasowania wzorca na przycisku mapy w nagłówku funkcji. Czy jest jakiś sposób na zrobienie tego? Próbuję uruchomić inny kod w zależności od tego, czy dany klucz już istnieje na mapie, czy też nie (a także chciałbym go uniknąć, jeśli) i/tak i tym razem).Jak wykonać dopasowywanie do wzorca na klawiszach mapy w głowicach funkcyjnych w eliksirach

Oto, jak wygląda mój kod:

def my_func(key, %{key => _} = map), do: ... 

co daje mi ten błąd

** (CompileError) nielegalne użycie klucza zmiennej wewnątrz mapy meczu kluczowej, mapy może się równać tylko na istniejącej zmiennej za pomocą^klucz

Oczywiście ja również próbowałem go za pomocą ^

def my_func(key, %{^key => _} = map), do: ... 

które następnie daje

** (CompileError) Bez ograniczeń zmienna^klucz

Używam eliksiru 1.3.1/erlang 19,0 x64 na maszynie z systemem Windows 8.1. Dzięki za przeczytanie!

Odpowiedz

12

Wystarczy wzór mecz z kluczem trzeba:

defmodule Test do 
    def my_func(%{"a" => value}), do: {:a, value} 
    def my_func(%{"b" => value}), do: {:b, value} 
    def my_func(_), do: :error 
end 

Następnie w iex:

iex(1)> Test.my_func(%{"a" => 1}) 
{:a, 1} 
iex(2)> Test.my_func(%{"b" => 2}) 
{:b, 2} 

Również kolejność klauzul są ważne. Na przykład, jeśli starają się dopasować %{"b" => 2} ale masz następujące mapie %{"a" => 1, "b" => 2}, klucz "a" dopasuje pierwsze, ponieważ znajduje się w pierwszej klauzuli:

iex(3)> Test.my_func(%{"a" => 1, "b" => 2}) 
{:a, 1} 

Jeśli chcesz wygenerować coś dla każdego klawisza można dopasować Polecam inne podejście. Na przykład, jeśli chcesz mapować funkcję do tych kluczy:

defmodule Test0 do 
    def my_op({"times_2", value}), do: {"times_2", value * 2} 
    def my_op({"times_3", value}), do: {"times_3", value * 3} 
    def my_op({key, value}), do: {key, value} 

    def my_func(m) do 
    Enum.map(m, &my_op/1) |> Enum.into(%{}) 
    end 
end 

Więc co można uzyskać następujące:

iex(1)> Test0.my_func(%{"times_2" => 2, "times_3" => 3, "whatever" => 42}) 
%{"times_2" => 4, "times_3" => 9, "whatever" => 42} 

Aktualizacja zgodnie z uwagami do tej odpowiedzi

Ty nie można wzorzec dopasować klucz do zmiennej. Problem polega na tym, że kompilator musi wygenerować kod, aby wyszukać coś, czego jeszcze nie wie. Podczas dopasowywania wzorca zazwyczaj podajesz kompilatorowi wskazówki, co otrzyma. Dla kluczy w mapach wskazówka jest sama w sobie kluczem. W tym przypadku nawet wskazanie, że pierwszym argumentem powinien być klucz do wyszukania, nie wystarczy dla kompilatora. Więc twoim podejściem powinno być użycie instrukcji if:

defmodule Test2 do 
    def my_func(k, m) do 
    if Map.haskey?(k, m), do: warning(k, m), else: foo(k, m) 
    end 

    def warning(k, m) do 
    #Warning 
    m 
    end 

    # In this function you could apply the pattern matching 
    # described in the first part of this answer. 
    def foo(k, m) do 
    value = # do something 
    %{m | key => value} 
    end 
end 

Mam nadzieję, że to odpowie na twoje pytanie.

+0

Witam, dziękuję za odpowiedź.Ale prawdopodobnie powinienem wyjaśnić, że klucz w 'mój_func (klucz, _)' jest zmienną określoną w czasie wykonywania, nie jest znana w czasie kompilacji – bottlenecked

+0

OK, teraz częściowo rozumiem, co próbujesz zrobić. Dokładnie, co robi twoja funkcja? –

+0

Hm, nie sądziłem, że istotne jest dodanie treści funkcji, ale kod końcowy będzie mniej więcej "jeśli klucz już istnieje, wywołaj ostrzeżenie, w przeciwnym razie wykonaj foo i dodaj go do mapy" – bottlenecked

Powiązane problemy