অ্যারে, বিটস্ট্রিং বা স্ট্রিংয়ের মতো এনিউমারেবলগুলোর ভেতর দিয়ে রিকার্সন করার সময় প্রায়ই দুটি বিষয় নিয়ে ভাবতে হয়:
এই বিষয়গুলো সামলানোর জন্য একটি অ্যাকুমুলেটর ব্যবহার করা যায়।
অ্যাকুমুলেটর হলো এমন একটি ভ্যারিয়েবল, যা ডেটার সাথে সাথে অতিরিক্ত হিসেবে পাঠানো হয়। ফাংশনের এক্সিকিউশনের বর্তমান অবস্থা এক ফাংশন কল থেকে পরের ফাংশন কলে পৌঁছে দিতে এটি ব্যবহার করা হয়, যতক্ষণ না বেস কেস-এ পৌঁছানো যায়। বেস কেসে পৌঁছে অ্যাকুমুলেটর দিয়ে রিকার্সিভ ফাংশন কলের চূড়ান্ত মান রিটার্ন করা হয়।
অ্যাকুমুলেটর ইনিশিয়ালাইজ করা উচিত ফাংশনের লেখকের, ফাংশনের ব্যবহারকারীর নয়। এটি করার জন্য দুটি ফাংশন ডিক্লেয়ার করতে হয়: একটি পাবলিক ফাংশন, যা কেবল প্রয়োজনীয় ডেটাকে আর্গুমেন্ট হিসেবে নেয় এবং অ্যাকুমুলেটর ইনিশিয়ালাইজ করে, আর একটি প্রাইভেট ফাংশন, যা অ্যাকুমুলেটরও নেয়। 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টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।