Elixir 1.7 - Enumerable

अनगिनत प्रोटोकॉल




elixir

अनगिनत प्रोटोकॉल

Enumerable प्रोटोकॉल Enum और Stream मॉड्यूल द्वारा उपयोग किया जाता है।

जब आप Enum मॉड्यूल में एक फ़ंक्शन शुरू करते हैं, तो पहला तर्क आमतौर पर एक संग्रह होता है जिसे इस प्रोटोकॉल को लागू करना चाहिए। उदाहरण के लिए, अभिव्यक्ति:

Enum.map([1, 2, 3], &(&1 * 2))

कम करने वाले ऑपरेशन को करने के लिए Enumerable.reduce/3 को आमंत्रित करता है जो संग्रह में प्रत्येक तत्व पर मैपिंग फ़ंक्शन &(&1 * 2) को मैप करके सूची बनाता है और संचित सूची के साथ तत्व का उपभोग करता है।

आंतरिक रूप से, Enum.map/2 को निम्नानुसार लागू किया जाता है:

def map(enumerable, fun) do
  reducer = fn x, acc -> {:cont, [fun.(x) | acc]} end
  Enumerable.reduce(enumerable, {:cont, []}, reducer) |> elem(1) |> :lists.reverse()
end

ध्यान दें कि उपयोगकर्ता द्वारा प्रदत्त फ़ंक्शन को reducer/0 फ़ंक्शन में लपेटा गया है। reducer/0 फ़ंक्शन को प्रत्येक चरण के बाद टैग की गई ट्यूपल को वापस करना होगा, जैसा कि acc/0 प्रकार में वर्णित है। अंत में, Enumerable.reduce/3 रिटर्न result/0

यह प्रोटोकॉल Reducer फ़ंक्शन और प्रोटोकॉल को लागू करने वाले डेटा प्रकार के बीच सूचना का आदान-प्रदान करने के लिए टैग किए गए ट्यूपल्स का उपयोग करता है। यह संसाधनों की गणना करने की अनुमति देता है, जैसे कि फ़ाइलें, कुशलतापूर्वक किया जाना चाहिए, जबकि संसाधन की गारंटी देना भी ज्ञान के अंत में बंद हो जाएगा। यह प्रोटोकॉल एन्यूमरेशन को स्थगित करने की भी अनुमति देता है, जो तब उपयोगी होता है जब कई एन्यूमरैबल्स के बीच इंटरलाविंग की आवश्यकता होती है (जैसे ज़िप में)।

इस प्रोटोकॉल को लागू करने के लिए चार कार्यों की आवश्यकता होती है, reduce/3 , count/1 , member?/2 , और slice/1 । प्रोटोकॉल का मूल reduce/3 फ़ंक्शन है। अन्य सभी कार्य डेटा संरचनाओं के लिए अनुकूलन पथ के रूप में मौजूद हैं जो कुछ गुणों को रैखिक समय से बेहतर तरीके से लागू कर सकते हैं।

सारांश

प्रकार

acc/0

प्रत्येक चरण के लिए संचायक मान

continuation()

आंशिक रूप से लागू कम फ़ंक्शन

reducer/0

Reducer फ़ंक्शन

result/0

कम संचालन का परिणाम है

slicing_fun()

एक स्लाइसिंग फ़ंक्शन जो स्लाइस में प्रारंभिक स्थिति और तत्वों की संख्या प्राप्त करता है

t()

कार्य

count/1

गणना करने योग्य तत्वों की संख्या को पुनः प्राप्त करता है

member?/2

जाँचता है कि क्या कोई तत्व मौजूद है

reduce/3

एक तत्व में enumerable कम कर देता है

slice/1

एक ऐसे फ़ंक्शन को लौटाता है जो डेटा संरचना को आकस्मिक रूप से स्लाइस करता है

प्रकार

एसीसी ()

acc() :: {:cont, term()} | {:halt, term()} | {:suspend, term()}

प्रत्येक चरण के लिए संचायक मान।

यह निम्नलिखित टैग में से एक के साथ एक टैग्ड टपल होना चाहिए:

  • :cont - गणना जारी रखना चाहिए
  • :halt - संलयन तुरंत रुक जाना चाहिए
  • :suspend - एन्यूमरेशन को तुरंत निलंबित किया जाना चाहिए

संचायक मान के आधार पर, Enumerable.reduce/3 द्वारा लौटा परिणाम बदल जाएगा। कृपया अधिक जानकारी के लिए result/0 प्रकार के दस्तावेज़ देखें।

यदि कोई reducer/0 फ़ंक्शन रिटर्न देता है :suspend संचयकर्ता :suspend , तो इसे स्पष्ट रूप से कॉलर द्वारा नियंत्रित किया जाना चाहिए और कभी भी रिसाव नहीं होना चाहिए।

निरंतरता ()

continuation() :: (acc() -> result())

आंशिक रूप से लागू कम फ़ंक्शन।

निरंतरता एक बंद परिणाम के रूप में वापस आ जाती है जब गणना को निलंबित कर दिया जाता है। जब आह्वान किया जाता है, तो यह एक नए संचायक की अपेक्षा करता है और यह परिणाम लौटाता है।

एक निरंतरता को तुच्छ रूप से तब तक लागू किया जा सकता है जब तक कि एक पूंछ पुनरावर्ती फैशन में कम फ़ंक्शन को परिभाषित किया गया हो। यदि फ़ंक्शन पूंछ पुनरावर्ती है, तो सभी राज्य को तर्क के रूप में पारित किया जाता है, इसलिए निरंतरता आंशिक रूप से लागू होने वाले कम करने वाले फ़ंक्शन है।

कम करने ()

reducer() :: (term(), term() -> acc())

Reducer फ़ंक्शन।

गणना करने योग्य तत्व और संचायक सामग्री के साथ बुलाया जाना चाहिए।

अगले गणन चरण के लिए संचायक लौटाता है।

परिणाम()

result() ::
  {:done, term()} | {:halted, term()} | {:suspended, term(), continuation()}

कम संचालन का परिणाम है।

यह तब किया जा सकता है जब एन्यूमरेशन को उसके अंत तक पहुंचकर समाप्त कर दिया जाता है , या जब एन्यूमरेशन को रोक दिया जाता है या reducer/0 फ़ंक्शन द्वारा निलंबित कर दिया जाता है, तो उसे रोक दिया जाता है।

यदि कोई reducer/0 फ़ंक्शन देता है :suspend संचयकर्ता :suspend करें :suspended टपल को स्पष्ट रूप से कॉलर द्वारा नियंत्रित किया जाना चाहिए और कभी भी रिसाव नहीं होना चाहिए। व्यवहार में, इसका मतलब है कि नियमित गणना कार्यों के बारे में चिंतित होने की जरूरत है :done और :halted परिणाम।

इसके अलावा, a :suspend कॉल हमेशा एक और कॉल द्वारा पीछा किया जाना चाहिए, अंत में रुक या अंत तक जारी रहेगा।

slicing_fun ()

slicing_fun() ::
  (start :: non_neg_integer(), length :: pos_integer() -> [term()])

एक स्लाइसिंग फ़ंक्शन जो स्लाइस में प्रारंभिक स्थिति और तत्वों की संख्या प्राप्त करता है।

start स्थिति एक संख्या >= 0 और गणना करने योग्य होने की गारंटी है। लंबाई एक संख्या है >= 1 इस तरह से start + length <= count कि start + length <= count , जहां count करने योग्य तत्वों में अधिकतम मात्रा है।

फ़ंक्शन को एक गैर खाली सूची वापस करना चाहिए जहां तत्वों की मात्रा length बराबर है।

टी ()

t() :: term()

कार्य

गिनती (गणनीय)

गणना करने योग्य तत्वों की संख्या को पुनः प्राप्त करता है।

यदि आप गणना योग्य तत्वों की संख्या की गणना कर सकते हैं तो इसे {:ok, count} वापस करना चाहिए।

अन्यथा यह {:error, __MODULE__} और एक डिफ़ॉल्ट एल्गोरिथ्म को reduce/3 ऊपर बनाया जाना चाहिए जो रैखिक समय में चलता है।

सदस्य (गणना करने योग्य, तत्व)

जाँचता है कि क्या कोई तत्व मौजूद है।

यदि आप पूरे गणना योग्य को पार किए बिना ===/2 साथ गणना में दिए गए तत्व की सदस्यता की जांच कर सकते हैं तो यह {:ok, boolean} वापस आ जाना चाहिए।

अन्यथा यह {:error, __MODULE__} और एक डिफ़ॉल्ट एल्गोरिथ्म को reduce/3 ऊपर बनाया जाना चाहिए जो रैखिक समय में चलता है।

कम (असंख्य, एसीसी, मज़ा)

एक तत्व में enumerable कम कर देता है।

Enum अधिकांश संचालन को कम करने के संदर्भ में लागू किया गया है। यह फ़ंक्शन प्रत्येक आइटम में दिए गए reducer/0 फ़ंक्शन को लागू करने योग्य होना चाहिए और लौटे संचायक द्वारा अपेक्षित रूप से आगे बढ़ना चाहिए।

अधिक जानकारी के लिए result/0 और acc/0 प्रकार के दस्तावेज देखें।

उदाहरण

एक उदाहरण के रूप में, यहां सूचियों को reduce करने का कार्यान्वयन है:

def reduce(_list, {:halt, acc}, _fun), do: {:halted, acc}
def reduce(list, {:suspend, acc}, fun), do: {:suspended, acc, &reduce(list, &1, fun)}
def reduce([], {:cont, acc}, _fun), do: {:done, acc}
def reduce([head | tail], {:cont, acc}, fun), do: reduce(tail, fun.(head, acc), fun)

टुकड़ा (गणनीय)

एक ऐसे फ़ंक्शन को लौटाता है जो डेटा संरचना को आकस्मिक रूप से स्लाइस करता है।

यह वापस करना चाहिए {:ok, size, slicing_fun} यदि {:ok, size, slicing_fun} पास एक ज्ञात बाउंड है और सभी पिछले तत्वों को ट्रेस किए बिना {:ok, size, slicing_fun} में स्थिति तक पहुंच सकता है।

अन्यथा यह {:error, __MODULE__} और एक डिफ़ॉल्ट एल्गोरिथ्म को reduce/3 ऊपर बनाया जाना चाहिए जो रैखिक समय में चलता है।

count/1 अंतर count/1

इस फ़ंक्शन द्वारा लौटाया गया size मान सीमा जाँच के लिए उपयोग किया जाता है, इसलिए यह अत्यंत महत्वपूर्ण है कि यह फ़ंक्शन केवल वापस लौटे :ok यदि गणना करने योग्य का size सस्ता है, तेज़ है और लगातार समय लेता है। अन्यथा सरलतम संचालन, जैसे Enum.at(enumerable, 0) , बहुत महंगा हो जाएगा।

दूसरी ओर, इस प्रोटोकॉल में count/1 फ़ंक्शन को लागू किया जाना चाहिए जब भी आप संग्रह में तत्वों की संख्या की गणना कर सकते हैं।