2015-10-21 16 views
28

Desen eşlemeyle oynayacağım bir şey buldum ve boş bir haritaya karşı bir yöntemin parametrelerini eşleştirmek çok kolay olmadığını öğrendim. Ben böyle bir şey giderdim düşündüm:Desen eşleme işlevi boş haritaya karşı

defmodule PatternMatch do 
    def modify(%{}) do 
    %{} 
    end 

    def modify(map) do 
    # expensive operation 
    %{ modified: "map" } 
    end 
end 

Ama ilk fonksiyon fıkra keyfi haritalar maçları gibi görünüyor:

iex> PatternMatch.modify(%{a: "map"}) 
==> %{} 

boş haritalar denetlemek için başka bir yolu var mı?

+0

İşlev cümlelerinin sırası da bu konuyla ilgilenir mi? Boş bir haritanın her zaman eşleşmesi ve bu nedenle son işlev cümlesi olması gerekir mi? –

cevap

49

Bu şekilde tasarım ile çalışır, ancak ilk bakışta biraz kafa karıştırıcı olabilir. Bu özellik, tüm anahtarları belirtmek zorunda kalmadan desen eşleştirmesi kullanarak haritaları imha etmenize olanak tanır. Örneğin:

iex> %{b: value} = %{a: 1, b: 2, c: 3} 
%{a: 1, b: 2, c: 3} 

iex> value 
2 

Sonuç olarak, %{} herhangi haritayı eşleşir.

(boş bir harita için kullanırsınız) @ PatrickOscity cevabı ek olarak
defmodule PatternMatch do 
    def modify(map) when map == %{} do 
    %{} 
    end 

    def modify(map) do 
    # ... 
    end 
end 
17

, bir map_size/1 bekçi kullanabilirsiniz: Eğer bir işlev boş bir harita ile eşleşme istiyorsanız, bir bekçi maddesini kullanmak zorunda tuşları bir dizi haritalara karşı maç için:

iex(6)> Kernel.match?(map when map_size(map) == 1, %{}) 
false 
iex(7)> Kernel.match?(map when map_size(map) == 1, %{foo: "bar"}) 
true 
+4

Güzel ekleme. Küçük düzeltme: "map_size (map) ..." yerine "map_size ..." yerine –

+0

olmalıdır. Teşekkürler. – Gazler

0

: Burada

defmodule PatternMatch do 
    def modify(map) when map_size(map) == 0 do 
    %{} 
    end 

    def modify(map) when map_size(map) == 1 do 
    #something else 
    end 

    def modify(map) do 
    # expensive operation 
    %{ modified: "map" } 
    end 
end 

eylem map_size/1 göstermek için Kernel.match?/2 kullanarak IEX gelen bir çıkıştır Şimdiye kadar sağlanan tüm harika cevaplara ek olarak, bir şapka veya bir üst ok noktası gibi görünen unary pin operator'un kullanımını da düşünebilirsiniz. seçmek yerine mevcut değişkenin değerine karşılık desen maç istediğinizde

pim operatörünü^kullanın: İlgili belgelerinde belirtildiği gibi, onun değerine karşılık size desen maçı sağlamak için onunla bir değişkeninin önüne için kullanabilirsiniz Eğer olarak doğrulayabilir

defmodule A do 
    def determine_map_volume(some_map) do 
    an_empty_map = %{} 

    some_map 
    |> case do 
    ^an_empty_map -> :empty # Application of pin operator 
    _ -> :not_empty 
    end 
    end 
end 

şu:

ardından değişkeni

yeniden bağlama örneğidir

A.determine_map_volume(%{}) 
:empty 
A.determine_map_volume(%{a: 1}) 
:not_empty 

Kullanmak istediğiniz yöntem, kodunuzun okunabilirliği için kişisel/kurumsal tercihinize bağlıdır.