जब आप एन्यूमरेबल्स (ऐरे, बिटस्ट्रिंग, स्ट्रिंग) पर रिकर्शन करते हैं, तो अक्सर दो बातों का ध्यान रखना होता है:
इन चिंताओं से निपटने के लिए एक एक्युमुलेटर का उपयोग किया जा सकता है।
एक्युमुलेटर एक वेरिएबल होता है जिसे डेटा के साथ-साथ आगे भी भेजा जाता है। इसका उपयोग फंक्शन के निष्पादन की वर्तमान स्थिति को एक फंक्शन कॉल से दूसरे फंक्शन कॉल तक पहुँचाने के लिए किया जाता है, और यह तब तक चलता रहता है जब तक बेस केस न आ जाए। बेस केस में इस एक्युमुलेटर की मदद से रिकर्सिव फंक्शन कॉल की अंतिम वैल्यू लौटाई जाती है।
एक्युमुलेटर को शुरुआती वैल्यू फंक्शन को लिखने वाले को ही देनी चाहिए, फंक्शन इस्तेमाल करने वाले को नहीं। ऐसा करने के लिए दो फंक्शन घोषित कीजिए: एक पब्लिक फंक्शन, जो आर्गुमेंट के रूप में सिर्फ ज़रूरी डेटा लेता है और एक्युमुलेटर को शुरुआती वैल्यू देता है, और एक प्राइवेट फंक्शन, जो एक्युमुलेटर भी लेता है। Elixir में यह एक आम तरीका है कि प्राइवेट फंक्शन के नाम के आगे do_ लगा दिया जाए।
# Count the length of a list without an accumulator
def count([]), do: 0
def count([_head | tail]), do: 1 + count(tail)
# Count the length of a list with an accumulator
def count(list), do: do_count(list, 0)
defp do_count([], count), do: count
defp do_count([_head | tail], count), do: do_count(tail, count + 1)
एक्युमुलेटर के उपयोग से हम रिकर्सिव फंक्शन को टेल-रिकर्सिव फंक्शन में बदल सकते हैं। कोई फंक्शन तब टेल-रिकर्सिव होता है जब वह जो सबसे अंतिम काम करता है, वह खुद को कॉल करना हो।
आपकी DNA रिसर्च लैब में आप स्टोरेज की जगह बचाने के लिए अपने रिसर्च डेटा को छोटा करने के अलग-अलग तरीके आज़माते रहे हैं। आपके एक साथी सुझाव देते हैं कि DNA डेटा को बाइनरी रूप में बदल दिया जाए:
| न्यूक्लिक अम्ल | कोड |
|---|---|
| स्पेस | 0000 |
| A | 0001 |
| C | 0010 |
| G | 0100 |
| T | 1000 |
आप इस पर सोचते हैं। इससे ज़रूरी डेटा स्टोरेज की लागत संभवतः आधी हो सकती है, हालाँकि इससे इंसानों के लिए डेटा पढ़ना कठिन हो जाएगा। अपनी बचत का आकलन करने के लिए आप एक ऐसा मॉड्यूल लिखने का फैसला करते हैं जो आपके डेटा को एनकोड और डिकोड करे।
encode_nucleotide/1 लागू कीजिए। यह न्यूक्लिक अम्ल का कोड पॉइंट लेकर एनकोड किए गए कोड की पूर्णांक वैल्यू लौटाता है।
DNA.encode_nucleotide(?A)
# => 1
# (which is equal to 0b0001)
अब decode_nucleotide/1 लागू कीजिए। यह एनकोड किए गए कोड की पूर्णांक वैल्यू लेकर न्यूक्लिक अम्ल का कोड पॉइंट लौटाता है।
DNA.decode_nucleotide(0b0001)
# => 65
# (which is equal to ?A)
encode/1 लागू कीजिए, जो न्यूक्लिक अम्लों और गैपों की चारलिस्ट लेकर एनकोड किए गए डेटा की बिटस्ट्रिंग लौटाए।
DNA.encode(~c"AC GT")
# => <<18, 4, 8::size(4)>>
अंत में decode/1 लागू कीजिए। यह न्यूक्लिक अम्लों और गैपों की बिटस्ट्रिंग लेकर डिकोड किए गए डेटा को चारलिस्ट के रूप में लौटाता है।
DNA.decode(<<132, 2, 1::size(4)>>)
# => ~c"TG CA"
Exercism पर साइन अप कीजिए और Elixir को 58 कॉन्सेप्ट168 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।