2014-07-16 8 views
12

मेरे पास एक ऐसा कार्य है जो कई चाबियों वाला नक्शा प्राप्त करता है, उनमें से कुछ वैकल्पिक हैं। वैकल्पिक कुंजी को कुछ डिफ़ॉल्ट करने की अनुमति देते हुए मैं मानचित्र को समझने के फ़ंक्शन हस्ताक्षर कैसे लिख सकता हूं?वैकल्पिक कुंजी के साथ पैटर्न मिलान मानचित्र

def handle_my_map(%{text: text, 
        print_times: print_times, # this I want to default to 2 
        color: color # this I want to default to "Blue" 
    }) do 
    Enum.each(1..print_times, fn (_) -> IO.puts ["(", color, "): ", text] end) 
end 

Test.handle_my_map(%{text: "here", print_times: 5, color: "Red"}) 
# (Red): here 
# (Red): here 
# (Red): here 
# (Red): here 
# (Red): here 

handle_my_map(%{text: "there"}) 
# => MatchError! 

मैं इसे होना चाहते हैं:

handle_my_map(%{text: "where", print_times: 3}) 
# (Blue): where 
# (Blue): where 
# (Blue): where 
handle_my_map(%{text: "there"}) 
# (Blue): there 
# (Blue): there 

कुछ माणिक के खोजशब्द तर्क की तरह:

def handle_my_map(text: nil, print_times: 2, color: 'Blue') 
+0

इस 'handle_my_map/1' एक पैरामीटर लेता है? –

+0

@ Зелёный - हाँ, एक नक्शा पैरामीटर –

उत्तर

10

आप Map.merge/2 उपयोग कर सकते हैं:

defmodule Handler do 
    @defaults %{print_times: 2, color: "Blue"} 

    def handle_my_map(map) do 
    %{text: text, print_times: times, color: color} = merge_defaults(map) 
    Enum.each(1..times, fn (_) -> IO.puts ["(", color, "): ", text] end) 
    end 

    defp merge_defaults(map) do 
    Map.merge(@defaults, map) 
    end 
end 

आप निल्स की अनुमति देना चाहते हैं, तो आप Map.merge/3 का उपयोग करें और के लिए merge_defaults/1 बदल सकते हैं:

defp merge_defaults(map) do 
    Map.merge(@defaults, map, fn _key, default, val -> val || default end) 
end 
+0

धन्यवाद, मैं कोशिश करूँगा। क्या आपके पास गहरी विलय के लिए भी सुझाव है? –

+2

यदि सभी मान नक्शे हैं, तो आप यहां कुछ भी करने के समान कुछ कर सकते हैं: https://github.com/elixir-lang/elixir/blob/master/lib/mix/lib/mix/config.ex#L192- एल 1 9 6 यदि नहीं, तो आपको केवल यह जांचने की आवश्यकता है कि दोनों मान नक्शे हैं या फिर Map.merge/2 पर कॉल करें। –

+1

स्पष्टीकरण के लिए, "निल्स को अनुमति दें" का अर्थ डिफ़ॉल्ट रूप से नाइल्स को ओवरराइट करना है। बीटीडब्ल्यू, यह उत्तर 'Map.merge' के लिए एक अच्छा दस्तावेज़ के रूप में कार्य करता है क्योंकि दस्तावेज़ अभी तक Elixir स्थापना में मौजूद नहीं है। – Kelvin

0

खैर। मुझे लगता है कि आपको %{a: a, b: b} तर्क के साथ एक और handle_my_map फ़ंक्शन लिखना होगा। इस तरह:

def handle_my_map(%{a: a, b: b, optional_c: c}) do 
    a + b + c 
    end 

    def handle_my_map(%{a: a, b: b}) do 
    a + b 
    end 

    YourModule.handle_my_map %{a: 1, b: 2} 
    #=> 3 
    YourModule.handle_my_map %{a: 1, b: 2, optional_c: 3} 
    #=> 6 

अमृत एक समारोह handle_my_map जो arity 1 अंत के साथ काम करता है जब तक अपने तर्क से मेल खाता है

+0

हाँ, लेकिन अगर 5 वैकल्पिक पैरामीटर हैं तो क्या होगा? मुझे 32 ('2^5') कार्यान्वयन की आवश्यकता होगी ... –

+0

तो आप पैटर्न मिलान का उपयोग नहीं कर सकते हैं। आप इसके बजाय ऐसा कुछ कर सकते हैं: 'def handle_my_map (मानचित्र), करें: नक्शा [: ए] + मानचित्र [: बी] + zero_if_nil (मानचित्र [: वैकल्पिक_c]) ', जहां' zero_if_nil/1' एक और सहायक कार्य है । – vforvova

3

मैं शायद कुछ इस तरह के साथ जाना होगा के लिए खोज करेंगे:

defmodule Handler do 
    @defaults %{print_times: 2, color: "Blue"} 

    def handle_my_map(map) do 
    %{text: text, print_times: times, color: color} = Dict.put_new(map, @defaults) 
    Enum.each(1..times, fn (_) -> IO.puts ["(", color, "): ", text] end) 
    end 
end 

हैं आपको मौजूदा कुंजी के साथ nil मानों को संभालने की आवश्यकता है, आप यह कर सकते हैं:

defmodule Handler do 
    @defaults %{print_times: 2, color: "Blue"} 

    def handle_my_map(map) do 
    %{text: text, print_times: times, color: color} = @defaults 
    |> Dict.merge(map) 
    |> Enum.into %{}, fn 
     {key, nil} -> {key, @defaults[key]} 
     {key, val} -> {key, val} 
    end 

    Enum.each(1..times, fn (_) -> IO.puts ["(", color, "): ", text] end) 
    end 
end 
+0

आपके संशोधित प्रश्न को संबोधित करने के लिए संपादित :) –

+0

धन्यवाद, मैं इसे आज़माउंगा। हालांकि यह एक छोटी सी वर्बोज़ दिखता है, शायद यदि एक से अधिक स्थानों के लिए इसकी आवश्यकता है, तो यह मैक्रो के लिए एक अच्छा उम्मीदवार है ... –

+0

इस तरह के कार्य के लिए कोड जनरेशन आवश्यक नहीं है। मैं इसे पुन: प्रयोज्यता के बजाय 'merge_with_defaults (my_map, the_defaults)' func पर निकालेगा। –

संबंधित मुद्दे