Ranges Library (C++20 এ নতুন)

সি++ স্ট্যান্ডার্ড লাইব্রেরি (C++ Standard Library) - Computer Programming

445

C++20 এ Ranges লাইব্রেরি একটি নতুন এবং শক্তিশালী লাইব্রেরি যা কনটেইনার ও ডেটা স্ট্রাকচারগুলোর উপাদানগুলির উপর আরও সহজ ও কার্যকর উপায়ে কাজ করতে সহায়তা করে। এটি মূলত Standard Template Library (STL) এর আলাদা এক্সটেনশন হিসেবে কাজ করে এবং প্রচলিত অ্যালগরিদম ও কনটেইনারের সীমাবদ্ধতাগুলো দূর করে। Ranges লাইব্রেরি ব্যবহার করে ডেটা ফিল্টারিং, ট্রান্সফর্মেশন, প্রজেকশন ও অন্যান্য অনেক কাজকে সহজ এবং কার্যকরী করা যায়।


Ranges লাইব্রেরির প্রধান বৈশিষ্ট্য

  1. রেঞ্জ ভিত্তিক অ্যালগরিদম (Range-based algorithms): পূর্বে ব্যবহৃত অ্যালগরিদমের মতোই, তবে এগুলো এখন কনটেইনারের পুরো ভিউ হিসেবে কাজ করে।
  2. ভিউস (Views): এটি এমন একটি লেজি কম্পিউটেশন মডেল যা বড় ডেটা সেটের উপর কাজ করার সময় প্রয়োজনীয় পারফরম্যান্স সরবরাহ করে।
  3. কম্পোজেবলিটি: Ranges লাইব্রেরি দিয়ে একাধিক অপারেশন কম্পোজ করা যায়, যেমন চেইনিং (chaining) এর মাধ্যমে ফিল্টার এবং ট্রান্সফর্মের কাজ একত্রে করা।
  4. লেজি ইভ্যালুয়েশন (Lazy Evaluation): শুধু প্রয়োজন অনুযায়ী ডেটা প্রক্রিয়াকরণ, যা কম মেমোরি এবং প্রসেসিং পাওয়ার ব্যবহার করে।

Ranges লাইব্রেরির মূল উপাদান

  1. ranges::views: views বিভিন্ন ভিউ তৈরি করে, যেমন ফিল্টার করা, ট্রান্সফর্ম করা ইত্যাদি।
  2. ranges::algorithm: প্রচলিত STL অ্যালগরিদমের মতো, তবে এগুলো রেঞ্জের ওপর কাজ করে।
  3. ranges::iterator: ইটরেটর ব্যবহার করে কনটেইনারের মধ্য দিয়ে চলাচল সহজ করে।

উদাহরণ ১: ranges::views::filter এবং ranges::views::transform

filter ভিউ একটি রেঞ্জ থেকে নির্দিষ্ট শর্তের উপর ভিত্তি করে উপাদান নির্বাচন করে এবং transform ভিউ প্রতিটি উপাদানের উপর একটি নির্দিষ্ট অপারেশন প্রয়োগ করে।

#include <iostream>
#include <ranges>
#include <vector>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // ফিল্টার করে শুধু জোড় সংখ্যা নির্বাচন এবং ২ দিয়ে গুণ করা
    auto result = numbers | std::ranges::views::filter([](int n) { return n % 2 == 0; })
                           | std::ranges::views::transform([](int n) { return n * 2; });

    // ফলাফল প্রদর্শন
    for (int n : result) {
        std::cout << n << " ";
    }

    return 0;
}

ব্যাখ্যা:

  • std::ranges::views::filter: এটি শুধুমাত্র এমন উপাদান নির্বাচন করে যা শর্ত পূরণ করে।
  • std::ranges::views::transform: এটি প্রতিটি নির্বাচিত উপাদানের উপর নির্দিষ্ট অপারেশন (যেমন গুণ করা) প্রয়োগ করে।

উদাহরণ ২: ranges::views::take এবং ranges::views::drop

take একটি রেঞ্জের প্রথম কয়েকটি উপাদান গ্রহণ করে এবং drop একটি রেঞ্জের প্রথম কয়েকটি উপাদান বাদ দেয়।

#include <iostream>
#include <ranges>
#include <vector>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // প্রথম ৫টি উপাদান নেয়া
    auto firstFive = numbers | std::ranges::views::take(5);

    // প্রথম ৫টি উপাদান বাদ দেয়া
    auto afterFive = numbers | std::ranges::views::drop(5);

    std::cout << "First 5 elements: ";
    for (int n : firstFive) {
        std::cout << n << " ";
    }

    std::cout << "\nAfter first 5 elements: ";
    for (int n : afterFive) {
        std::cout << n << " ";
    }

    return 0;
}

ব্যাখ্যা:

  • std::ranges::views::take: এটি রেঞ্জের প্রথম ৫টি উপাদান গ্রহণ করে।
  • std::ranges::views::drop: এটি রেঞ্জের প্রথম ৫টি উপাদান বাদ দেয়।

উদাহরণ ৩: ranges::views::reverse

reverse ভিউ ব্যবহার করে উপাদানগুলোর ক্রম উল্টো করা যায়।

#include <iostream>
#include <ranges>
#include <vector>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    // উপাদানগুলোর ক্রম উল্টো করা
    auto reversed = numbers | std::ranges::views::reverse;

    std::cout << "Reversed order: ";
    for (int n : reversed) {
        std::cout << n << " ";
    }

    return 0;
}

ব্যাখ্যা:

  • std::ranges::views::reverse: এটি উপাদানগুলোর ক্রম উল্টো করে, অর্থাৎ শেষ উপাদানটি প্রথমে আসে।

উদাহরণ ৪: ranges::views::iota এবং ranges::views::take_while

iota ভিউ একটি সংখ্যা থেকে শুরু করে একটি অনন্ত ক্রম তৈরি করে এবং take_while শর্ত পূরণ না হওয়া পর্যন্ত উপাদান গ্রহণ করে।

#include <iostream>
#include <ranges>

int main() {
    // ১ থেকে শুরু করে ১০ পর্যন্ত ক্রম তৈরি করা
    auto numbers = std::ranges::views::iota(1) | std::ranges::views::take_while([](int n) { return n <= 10; });

    for (int n : numbers) {
        std::cout << n << " ";
    }

    return 0;
}

ব্যাখ্যা:

  • std::ranges::views::iota: এটি ১ থেকে শুরু করে অনন্ত ক্রম তৈরি করে।
  • std::ranges::views::take_while: এটি শর্ত পূরণ না হওয়া পর্যন্ত ক্রম গ্রহণ করে, অর্থাৎ এখানে n <= 10

উপসংহার

C++20 এর Ranges লাইব্রেরি প্রোগ্রামারদের জন্য কনটেইনারের সাথে কাজ করা আরও সহজ এবং কার্যকর করে তুলেছে। এই লাইব্রেরি ব্যবহার করে আপনি ফিল্টারিং, ট্রান্সফরমেশন, প্রজেকশন এবং ক্রম উল্টো করাসহ বিভিন্ন কাজ খুব সহজে এবং লেজি ইভ্যালুয়েশন পদ্ধতিতে করতে পারেন। Ranges লাইব্রেরি কনটেইনার এবং অ্যালগরিদমের ক্ষমতাকে আরও প্রসারিত করে এবং কোডকে আরও পরিষ্কার ও পড়তে সহজ করে তোলে।

Content added By

C++20 তে Ranges মডিউল যুক্ত করা হয়েছে, যা প্রোগ্রামারদের আরও সহজে এবং কার্যকরীভাবে ডেটা প্রক্রিয়াকরণ করতে সাহায্য করে। std::ranges মডিউল মূলত একটি নতুন স্ট্যান্ডার্ড লাইব্রেরি মডিউল, যা range-based operations সহজে করতে সহায়তা করে। এটি STL (Standard Template Library) এর অ্যালগরিদম এবং কনটেইনারের ওপর আরও কার্যকরীভাবে কাজ করার উপায় প্রদান করে এবং পাইপলাইনিং, ল্যাম্বডা এক্সপ্রেশন, এবং ভিউ এর মাধ্যমে কোডকে সংক্ষিপ্ত এবং পঠনযোগ্য করে।


Ranges এর মৌলিক ধারণা

Ranges মডিউল ডেটা বা কনটেইনারকে পাইপলাইন স্টাইলে প্রক্রিয়াকরণ করতে দেয়। Ranges ব্যবহার করে প্রোগ্রামাররা বিভিন্ন ফিল্টারিং, ট্রান্সফরমেশন, এবং স্লাইসিং অপারেশন একত্রে পাইপলাইন আকারে সম্পাদন করতে পারেন।

Ranges এর মাধ্যমে:

  • কনটেইনার বা ডেটার উৎসের ওপর সরাসরি কাজ করা যায়।
  • পাইপলাইন স্টাইলে বিভিন্ন অপারেশন একত্রে লেখা যায়, যা কোডকে সংক্ষিপ্ত করে।
  • View এবং Action অপারেশন সরবরাহ করা হয়, যা ডেটার ওপর বিভিন্ন ধরণের ফিল্টারিং এবং ট্রান্সফরমেশন করতে সহায়ক।

Ranges মডিউলের মূল উপাদান

  1. Views: এটি কনটেইনার বা ডেটার উপর ফিল্টারিং, ট্রান্সফরমেশন ইত্যাদি অপারেশন সম্পন্ন করে। std::ranges::views নেমস্পেসের অধীনে বিভিন্ন ভিউ পাওয়া যায়।
  2. Actions: এটি সরাসরি ডেটার ওপর পরিবর্তনশীল অপারেশন সম্পাদন করে। std::ranges::actions নেমস্পেসের অধীনে পাওয়া যায়।
  3. Algorithms: std::ranges মডিউলে এমন অ্যালগরিদম আছে, যা std::algorithm এর মতোই কাজ করে, তবে এগুলো range-কে সরাসরি ইনপুট হিসেবে গ্রহণ করতে পারে।

Ranges ব্যবহার করার উদাহরণ

উদাহরণ ১: std::ranges::views::filter এবং std::ranges::views::transform

std::ranges::views::filter একটি ভিউ যা নির্দিষ্ট কন্ডিশন অনুসারে উপাদানগুলো ফিল্টার করে। std::ranges::views::transform প্রতিটি উপাদানে নির্দিষ্ট অপারেশন প্রয়োগ করে।

#include <iostream>
#include <vector>
#include <ranges>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // ফিল্টার করা যেসব সংখ্যা ৫ এর চেয়ে বড় এবং ট্রান্সফর্ম করা দ্বিগুণ করে
    auto result = numbers | std::ranges::views::filter([](int n) { return n > 5; })
                          | std::ranges::views::transform([](int n) { return n * 2; });

    // ফলাফল প্রিন্ট করা
    for (int n : result) {
        std::cout << n << " ";
    }

    return 0;
}

আউটপুট:

12 14 16 18 20

এখানে filter এবং transform ভিউ ব্যবহার করে শুধুমাত্র ৫ এর চেয়ে বড় সংখ্যাগুলোকে দ্বিগুণ করে দেখানো হয়েছে। পাইপলাইন অপারেশন ব্যবহার করে এটি আরও সহজ ও কার্যকরভাবে লেখা গেছে।


Ranges এর কিছু গুরুত্বপূর্ণ অপারেশন

  1. std::ranges::views::filter: এটি একটি ভিউ যা কনটেইনারের উপাদানগুলো থেকে নির্দিষ্ট শর্ত পূরণকারী উপাদানগুলো নির্বাচন করে।
  2. std::ranges::views::transform: এটি একটি ভিউ যা প্রতিটি উপাদানের উপর নির্দিষ্ট অপারেশন প্রয়োগ করে এবং পরিবর্তিত মান রিটার্ন করে।
  3. std::ranges::views::take: এটি একটি ভিউ যা একটি রেঞ্জের প্রথম কিছু উপাদান নেয়।
  4. std::ranges::views::drop: এটি একটি ভিউ যা একটি রেঞ্জের প্রথম কিছু উপাদান বাদ দেয়।
  5. std::ranges::views::reverse: এটি একটি ভিউ যা একটি রেঞ্জকে উল্টিয়ে দেয়।

উদাহরণ: std::ranges::views::take এবং std::ranges::views::reverse

#include <iostream>
#include <vector>
#include <ranges>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // প্রথম ৫ টি উপাদান নেয়া এবং উল্টানো
    auto result = numbers | std::ranges::views::take(5)
                          | std::ranges::views::reverse;

    // ফলাফল প্রিন্ট করা
    for (int n : result) {
        std::cout << n << " ";
    }

    return 0;
}

আউটপুট:

5 4 3 2 1

এখানে take ভিউ ব্যবহার করে প্রথম ৫টি উপাদান নেয়া হয়েছে এবং reverse ভিউ ব্যবহার করে সেগুলো উল্টানো হয়েছে।


Ranges এবং Traditional Approach এর তুলনা

Ranges ব্যবহার করে প্রোগ্রামিং করার প্রধান সুবিধা হলো এটি কোডকে সংক্ষিপ্ত এবং আরও পাঠযোগ্য করে তোলে।

Traditional ApproachRanges Approach
for লুপ এবং কন্ডিশন ব্যবহার প্রয়োজনপাইপলাইন অপারেশনে কোড ছোট এবং স্পষ্ট
কোড জটিল এবং বড় হতে পারেপাইপলাইনিং কোডকে সহজ ও পঠনযোগ্য করে
একাধিক ভেরিয়েবল বা লুপ প্রয়োজনসরাসরি কনটেইনারের উপর কাজ করা যায়

Ranges মডিউল ব্যবহারের সুবিধা

  • সহজ কোডিং: Ranges পাইপলাইন অপারেশন প্রদান করে, যা কোডকে সংক্ষিপ্ত ও সহজ করে।
  • কম্পোজিবিলিটি: Ranges মডিউলে বিভিন্ন অপারেশন একত্রে সহজে লেখা যায়।
  • কোডের পুনঃব্যবহারযোগ্যতা: একবার ভিউ তৈরি করলে সেটি পুনরায় ব্যবহার করা যায়।
  • উন্নত পঠনযোগ্যতা: পাইপলাইনিং এর মাধ্যমে কোড আরও পঠনযোগ্য এবং পরিচালনযোগ্য হয়।

উপসংহার

C++20 এর std::ranges মডিউল প্রোগ্রামারদের জন্য ডেটা ম্যানিপুলেশন সহজ এবং কার্যকর করেছে। এটি একটি পাইপলাইন ভিত্তিক অপারেশন, যা কনটেইনারের উপাদানগুলোর ওপর ফিল্টারিং, ট্রান্সফরমেশন, স্লাইসিং ইত্যাদি অপারেশন সহজে করতে সাহায্য করে। Ranges মডিউল ব্যবহার করে প্রোগ্রামিং আরও সুবিধাজনক ও পঠনযোগ্য হয়ে ওঠে, যা প্রোগ্রামারদের জন্য অনেক উপকারী।

Content added By

C++20 তে range-based algorithms এবং views প্রবর্তিত হয়েছে, যা C++ প্রোগ্রামিংয়ে ডেটার ওপর আরও দক্ষ এবং সোজা অপারেশন করার একটি নতুন পদ্ধতি প্রদান করেছে। Range-based algorithms স্ট্যান্ডার্ড লাইব্রেরির অ্যালগরিদমগুলোকে ranges এর উপর প্রয়োগ করতে সাহায্য করে, যা কোড লেখার অভিজ্ঞতা সহজ করে। Views মূলত একটি lazy evaluation কৌশল, যা ডেটার উপর অপারেশন করার সময় কার্যকারিতা বাড়ায় এবং অতিরিক্ত কপি বা অ্যাক্সেসের প্রয়োজনীয়তা কমিয়ে দেয়।

১. Range-based Algorithms

C++20 এর range-based algorithms অ্যালগরিদমগুলোকে স্ট্যান্ডার্ড লাইব্রেরির ranges লাইব্রেরির সাথে ব্যবহার করার জন্য ডিজাইন করা হয়েছে। এর মাধ্যমে আপনি সহজে ranges এবং containers এর উপরে অ্যালগরিদম প্রয়োগ করতে পারেন, যা একাধিক ধাপের অপারেশনকে কমপ্যাক্ট এবং স্পষ্টভাবে সংজ্ঞায়িত করতে সহায়ক।

উদাহরণ: std::ranges::for_each (Range-based algorithm)

std::ranges::for_each একটি রেঞ্জের প্রতিটি উপাদানের উপর একটি ফাংশন প্রয়োগ করতে ব্যবহৃত হয়, যা std::for_each এর মতো কাজ করে, তবে এখানে ranges এর উপর এটি কাজ করে এবং কোনও iterator ব্যবহারের প্রয়োজন হয় না।

#include <iostream>
#include <ranges>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // Range-based for_each ব্যবহার
    std::ranges::for_each(vec, [](int n) {
        std::cout << n * 2 << " ";  // প্রতিটি উপাদানের দ্বিগুণ মান প্রিন্ট করা
    });

    return 0;
}

আউটপুট:

2 4 6 8 10

এখানে, std::ranges::for_each ব্যবহার করে আমরা std::vector<int> এর প্রতিটি উপাদানের উপর একটি ফাংশন প্রয়োগ করেছি এবং প্রতি উপাদানের দ্বিগুণ মান প্রিন্ট করেছি। আপনি এটি ব্যবহার করে সরাসরি ranges এর উপর কাজ করতে পারেন।


২. Views: Lazy Evaluation

Views হল একটি লেটি (lazy) ডেটা প্রক্রিয়া যা ranges উপর অপারেশন করার সময় সমস্ত ডেটা কপি না করে শুধুমাত্র একটি ভিউ তৈরি করে। যখন আপনি একটি view তৈরি করেন, তখন এটি মূল ডেটাকে পরিবর্তন না করে তার উপর অপারেশনগুলো lazy evaluation পদ্ধতিতে করে। এর ফলে, view ডেটা কপি বা অতিরিক্ত মেমরি বরাদ্দ ছাড়াই ডেটার উপরে অপারেশন করতে সক্ষম হয়।

উদাহরণ: std::views::transform (View)

std::views::transform একটি view প্রদান করে যা একটি রেঞ্জের উপর কোনো ট্রান্সফরমেশন ফাংশন প্রয়োগ করে। এটি সঙ্গতিপূর্ণভাবে একে একে উপাদানগুলো পরিবর্তন করে, কিন্তু এটি ডেটার একটি কপি তৈরি করে না।

#include <iostream>
#include <ranges>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // View এর মাধ্যমে transform অপারেশন
    auto transformed = vec | std::views::transform([](int n) { return n * 3; });

    // transformed একটি view, তাই কপি করা হবে না
    for (int n : transformed) {
        std::cout << n << " ";
    }

    return 0;
}

আউটপুট:

3 6 9 12 15

এখানে, std::views::transform ব্যবহার করে, আমরা একটি view তৈরি করেছি যা vec এর প্রতিটি উপাদানকে তিন গুণ বাড়ায়, কিন্তু এটি ডেটার একটি কপি তৈরি করে না। Lazy evaluation এর মাধ্যমে view কেবলমাত্র যখন প্রয়োজন হবে তখনই প্রক্রিয়া করবে।


৩. std::ranges::filter (View)

std::ranges::filter একটি view তৈরি করে যা শুধুমাত্র সেই উপাদানগুলো রাখে যা একটি নির্দিষ্ট শর্ত পূর্ণ করে। এটি ranges এর মধ্যে filtering করতে ব্যবহৃত হয়।

#include <iostream>
#include <ranges>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5, 6};

    // View এর মাধ্যমে filter অপারেশন
    auto even_numbers = vec | std::views::filter([](int n) { return n % 2 == 0; });

    // filtered view থেকে উপাদান প্রিন্ট করা
    for (int n : even_numbers) {
        std::cout << n << " ";
    }

    return 0;
}

আউটপুট:

2 4 6

এখানে, std::ranges::filter ব্যবহার করে আমরা একটি view তৈরি করেছি যা শুধুমাত্র সেই উপাদানগুলো রাখে যা even (যাজ) সংখ্যা, এবং আবার কোনো অতিরিক্ত কপি ছাড়া এটি করা হয়েছে।


৪. std::ranges::sort (Range-based algorithm)

std::ranges::sort একটি নতুন রেঞ্জ-বেসড অ্যালগরিদম যা ranges এর মধ্যে উপাদানগুলোকে সরাসরি সাজায়। এটি আগে std::sort ব্যবহার করে সিকোয়েন্সের উপাদানগুলো সাজাতে হত, কিন্তু এখন ranges::sort এর মাধ্যমে ranges সরাসরি সাজানো সম্ভব।

#include <iostream>
#include <ranges>
#include <vector>

int main() {
    std::vector<int> vec = {5, 3, 8, 1, 4};

    // Range-based sort
    std::ranges::sort(vec);

    // সাজানো ভেক্টর প্রিন্ট করা
    for (int n : vec) {
        std::cout << n << " ";
    }

    return 0;
}

আউটপুট:

1 3 4 5 8

এখানে, std::ranges::sort ব্যবহার করে vec এর উপাদানগুলো সরাসরি সাজানো হয়েছে। এটি std::sort এর মতোই কাজ করে, তবে এখানে ranges সরাসরি সাজানো হচ্ছে এবং কোনো ইটরেটরের প্রয়োজন নেই।


৫. std::ranges::reduce (Range-based algorithm)

std::ranges::reduce একটি নতুন রেঞ্জ-বেসড অ্যালগরিদম যা একটি range এর উপর ফোল্ডিং অপারেশন (যেমন যোগফল বা গুণফল) করে।

#include <iostream>
#include <ranges>
#include <vector>
#include <numeric>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // Range-based reduce
    int sum = std::ranges::reduce(vec, 0);  // 0 হচ্ছে আদি মান

    std::cout << "Sum: " << sum << std::endl;

    return 0;
}

আউটপুট:

Sum: 15

এখানে, std::ranges::reduce ব্যবহার করে আমরা vec এর সব উপাদান যোগ করেছি।


উপসংহার

  • Range-based algorithms C++20 তে ranges এর উপর অপারেশন করার জন্য একটি উন্নত এবং পরিষ্কার পদ্ধতি সরবরাহ করে। এর মাধ্যমে আপনি সরাসরি ranges এর উপর অ্যালগরিদম প্রয়োগ করতে পারেন, যেটি std::for_each, std::sort, std::reduce ইত্যাদি অন্তর্ভুক্ত।
  • Views একটি lazy evaluation কৌশল যা ডেটার কপি ছাড়াই অপারেশন করতে সাহায্য করে। std::views::transform এবং std::views::filter এর মতো views ডেটার উপর কার্যকরী অপারেশন করতে সক্ষম।

C++20 এর ranges এবং views কৌশল ব্যবহার করে কোডটি আরও পরিষ্কার, নির্ভরযোগ্য এবং কার্যকরী হতে পারে, বিশেষত যখন বড় ডেটাসেটের সাথে কাজ করা হয়।

Content added By

C++20 থেকে range-based algorithms এবং views সংক্রান্ত নতুন বৈশিষ্ট্যগুলি lazy evaluation এবং range adaptors নিয়ে কাজ করার সুযোগ দিয়েছে, যা C++ প্রোগ্রামিংকে আরও শক্তিশালী, নমনীয় এবং কার্যকর করে তোলে। এই নতুন বৈশিষ্ট্যগুলি বিশেষভাবে রেঞ্জ লাইব্রেরি (ranges library) এর মধ্যে আসে, যা এলিমেন্টের মধ্যে ক্রম অনুসারে কাজ করতে সাহায্য করে এবং বিভিন্ন ফাংশনাল প্রোগ্রামিং ধারণা বাস্তবায়ন করতে সহজ করে তোলে।

১. Lazy Evaluation এবং Range Adaptors

Lazy Evaluation:

Lazy Evaluation হল একটি কৌশল, যেখানে কোনো অপারেশন তখনই সম্পাদিত হয় যখন ফলাফলের প্রয়োজন পড়ে। এর মানে হল যে, অপারেশনগুলি বিলম্বিতভাবে বা প্রয়োজনে করা হয়। C++20 এ, ranges লাইব্রেরির ব্যবহারের মাধ্যমে lazy evaluation সম্ভব হয়েছে। যখন আপনি একটি রেঞ্জের উপরে কোনো ফাংশন বা অ্যালগরিদম প্রয়োগ করেন, তখন তা কেবলমাত্র যখন আপনি রেঞ্জের উপাদানগুলি অ্যাক্সেস করবেন তখনই কার্যকর হবে, আগে নয়।

Lazy evaluation সাধারণত range adaptors ব্যবহার করে করা হয়। Range adaptors ফাংশনাল অপারেশন বা রূপান্তর কেবল তখনই সম্পাদন করে যখন এটি প্রয়োজন, এবং এটি সম্পাদন না করে ফলাফল কেবল ধারণ করে রাখে। এতে প্রোগ্রাম আরো কার্যকরী ও দ্রুত হয়, কারণ এটি অতিরিক্ত অপ্রয়োজনীয় কাজ কমায়।

উদাহরণ: Lazy Evaluation with Range Adaptors

#include <iostream>
#include <vector>
#include <ranges>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6};

    // lazy evaluation: transform applied only when iterating
    auto transformed = numbers 
                        | std::views::transform([](int n) { return n * 2; })
                        | std::views::filter([](int n) { return n % 2 == 0; });

    // Output elements lazily as we iterate over the result
    for (int n : transformed) {
        std::cout << n << " ";  // It will print only even results of the transformation
    }

    return 0;
}

আউটপুট:

4 8 12

এখানে, lazy evaluation ঘটছে, কারণ std::views::transform এবং std::views::filter কেবল তখনই কার্যকর হবে যখন রেঞ্জের উপাদানগুলি অ্যাক্সেস করা হবে, এবং প্রতিটি উপাদান একসাথে প্রসেস হবে না।


Range Adaptors:

Range adaptors হলো এমন ফাংশন বা কনসেপ্ট যা একটি রেঞ্জের উপাদানকে রূপান্তর করতে সহায়ক। এগুলি মূলত views এর অংশ, যা lazy evaluation এর সাহায্যে রেঞ্জের উপাদানগুলিতে বিভিন্ন ট্রান্সফর্মেশন, ফিল্টারিং, বা ম্যানিপুলেশন করে।

C++20 এর ranges লাইব্রেরিতে বিভিন্ন ধরনের range adaptors প্রদান করা হয়েছে যেমন:

  • std::views::transform: উপাদানগুলিকে রূপান্তর করা।
  • std::views::filter: উপাদানগুলিকে ফিল্টার করা।
  • std::views::reverse: রেঞ্জের উপাদানগুলিকে উল্টো করা।
  • std::views::take: রেঞ্জ থেকে নির্দিষ্ট সংখ্যক উপাদান নেয়া।
  • std::views::drop: রেঞ্জের উপাদানগুলো থেকে প্রথম কিছু উপাদান বাদ দেয়া।

২. Range Adaptors এর উদাহরণ

std::views::transform:

এটি রেঞ্জের প্রতিটি উপাদানকে একটি নির্দিষ্ট ফাংশন বা এক্সপ্রেশন দিয়ে রূপান্তর করে।

#include <iostream>
#include <vector>
#include <ranges>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    // Transform the numbers by multiplying each by 2
    auto transformed = numbers | std::views::transform([](int n) { return n * 2; });

    for (int n : transformed) {
        std::cout << n << " ";  // Output: 2 4 6 8 10
    }

    return 0;
}

আউটপুট:

2 4 6 8 10

এখানে, std::views::transform রেঞ্জের প্রতিটি উপাদানকে n * 2 দ্বারা রূপান্তর করছে, এবং এই প্রক্রিয়া কেবল তখনই করা হচ্ছে যখন উপাদানগুলি অ্যাক্সেস করা হচ্ছে।


std::views::filter:

এটি রেঞ্জ থেকে কিছু উপাদান ফিল্টার করে, যেমন কিছু শর্ত পূর্ণ হলে সেই উপাদানগুলো নির্বাচন করা হয়।

#include <iostream>
#include <vector>
#include <ranges>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6};

    // Filter even numbers
    auto even_numbers = numbers | std::views::filter([](int n) { return n % 2 == 0; });

    for (int n : even_numbers) {
        std::cout << n << " ";  // Output: 2 4 6
    }

    return 0;
}

আউটপুট:

2 4 6

এখানে, std::views::filter শুধুমাত্র ইভেন (even) সংখ্যাগুলোই নির্বাচন করছে।


৩. Combining Multiple Range Adaptors

আপনি একাধিক range adaptors একসাথে ব্যবহার করতে পারেন। যেমন আপনি transform এবং filter একসাথে ব্যবহার করতে পারেন, যা একই রেঞ্জের উপাদানগুলোকে একাধিক রূপে প্রক্রিয়া করবে।

#include <iostream>
#include <vector>
#include <ranges>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6};

    // Transform numbers by multiplying each by 2 and then filter the even ones
    auto transformed_and_filtered = numbers 
                                      | std::views::transform([](int n) { return n * 2; })
                                      | std::views::filter([](int n) { return n % 4 == 0; });

    for (int n : transformed_and_filtered) {
        std::cout << n << " ";  // Output: 4 8 12
    }

    return 0;
}

আউটপুট:

4 8 12

এখানে, প্রথমে প্রতিটি উপাদানকে n * 2 দিয়ে রূপান্তর করা হচ্ছে এবং তারপর শুধু n % 4 == 0 শর্ত পূর্ণকারী উপাদানগুলো filter করা হচ্ছে।


৪. Benefits of Lazy Evaluation and Range Adaptors

  • Performance: Lazy evaluation ফাংশনাল অপারেশনগুলিকে কেবল তখনই সম্পাদন করতে দেয় যখন সেগুলির ফলাফল প্রয়োজন হয়, যা অপ্রয়োজনীয় কাজ কমিয়ে দেয় এবং কর্মক্ষমতা বাড়ায়।
  • Memory Efficiency: Lazy evaluation ব্যবহারের ফলে, ডেটা একযোগে প্রক্রিয়া করার বদলে প্রয়োজনীয় অংশের উপরই কাজ করা হয়, যা মেমরি ব্যবস্থাপনাকে আরও কার্যকর করে।
  • Readability and Maintainability: Range adaptors ব্যবহার করে কোড আরও পরিষ্কার, সংক্ষিপ্ত এবং রিডেবল হয়, কারণ আপনি বড় বড় লুপ এবং ইফ স্টেটমেন্ট এড়াতে পারেন।

উপসংহার

Lazy Evaluation এবং Range Adaptors C++20-এ প্রবর্তিত শক্তিশালী ফিচার, যা প্রোগ্রামারদের আরও কার্যকরী এবং কার্যক্ষম কোড লিখতে সহায়ক। আপনি যখন range-based algorithms বা views ব্যবহার করেন, তখন আপনার কোড আরও সুন্দর এবং নমনীয় হয়ে ওঠে, এবং এর মাধ্যমে আপনি ডেটার উপর অত্যন্ত কার্যকরভাবে কাজ করতে পারেন।

Content added By

C++20 তে Ranges যোগ করা হয়েছে, যা কনটেইনারের উপর কাজ করার নতুন এবং শক্তিশালী উপায় প্রদান করে। Ranges লাইব্রেরি এমন ফাংশনাল প্রোগ্রামিং ধারণা অনুসরণ করে, যেখানে ডেটা ট্রাভার্সাল এবং ম্যানিপুলেশন আরো সহজ, কার্যকরী এবং ধারাবাহিকভাবে করা যায়। Ranges মূলত স্ট্যান্ডার্ড কনটেইনারগুলির সাথে ব্যবহার করার জন্য একটি নতুন ধরনের অ্যাবস্ট্রাকশন প্রদান করে, যা তাদের সাথে বিভিন্ন অ্যালগরিদম সংযুক্ত করতে সহজ করে তোলে।

Ranges লাইব্রেরির বৈশিষ্ট্য

Ranges লাইব্রেরি একটি নতুন API প্রদান করে, যা পরবর্তী সময়ে C++ কনটেইনারগুলির সাথে একত্রে কাজ করার জন্য ডিজাইন করা হয়েছে। এর কিছু বৈশিষ্ট্য হলো:

  1. Range-based View: কনটেইনারের উপাদানগুলোকে ইটারেটরের মতো অ্যাক্সেস করা যায়, কিন্তু কোড আরও পরিষ্কার এবং কমপ্যাক্ট হয়।
  2. Lazy Evaluation: Ranges লাইব্রেরির অ্যালগরিদমগুলো “lazy” উপায়ে কাজ করে, যার মানে হলো কেবলমাত্র যখন ফলাফল প্রয়োজন, তখনই কাজগুলো কার্যকর হয়।
  3. Composability: Ranges অ্যালগরিদমগুলোকে সহজে একসাথে কম্পোজ করা যায়, যার ফলে জটিল লজিক খুব কম কোডে লেখা সম্ভব হয়।

C++ এর অন্যান্য কনটেইনারের সাথে Ranges এর ইন্টিগ্রেশন

C++20 এর Ranges লাইব্রেরি অন্যান্য কনটেইনারের সাথে খুব সহজে কাজ করতে পারে। এটি মূলত কনটেইনারের উপাদানগুলোর উপর বিভিন্ন অ্যালগরিদম প্রয়োগ করতে সহায়তা করে, যেমন std::vector, std::list, std::array, std::map ইত্যাদি। এখানে Ranges লাইব্রেরি ব্যবহার করে কনটেইনারের সাথে ইন্টিগ্রেশন করার কিছু উদাহরণ দেওয়া হলো।


১. Ranges with std::vector

std::vector একটি বহুল ব্যবহৃত কনটেইনার, এবং ranges লাইব্রেরি ব্যবহার করে এটি আরও শক্তিশালী এবং ব্যবহারযোগ্য হয়।

উদাহরণ:

#include <iostream>
#include <vector>
#include <ranges>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // ranges লাইব্রেরি ব্যবহার করে ফিল্টার এবং ট্রান্সফর্ম করা
    auto result = vec | std::ranges::views::transform([](int n) { return n * n; })
                      | std::ranges::views::filter([](int n) { return n > 10; });

    // ফলাফল প্রিন্ট করা
    for (int n : result) {
        std::cout << n << " "; // আউটপুট: 16 25
    }

    return 0;
}

এখানে, std::ranges::views::transform এবং std::ranges::views::filter ব্যবহার করে আমরা std::vector এর উপাদানগুলোর উপর ট্রান্সফর্ম এবং ফিল্টার অপারেশনগুলো প্রয়োগ করেছি। এই ধরনের lazy evaluation এর মাধ্যমে ফলাফলটি কেবল তখনই তৈরি হয় যখন আমরা এটি ব্যবহার করি।


২. Ranges with std::list

std::list এর সাথে ranges লাইব্রেরির ইন্টিগ্রেশনও বেশ কার্যকর। কারণ list কনটেইনারটি একটি দ্বিমুখী সংযুক্ত তালিকা (doubly linked list) হওয়ার কারণে এটি রেঞ্জ অপারেশনে ভালো কাজ করে।

উদাহরণ:

#include <iostream>
#include <list>
#include <ranges>

int main() {
    std::list<int> lst = {1, 2, 3, 4, 5};

    // ranges এর মাধ্যমে ট্রান্সফর্ম এবং ফিল্টারিং
    auto result = lst | std::ranges::views::transform([](int n) { return n * 2; })
                      | std::ranges::views::filter([](int n) { return n % 4 == 0; });

    // ফলাফল প্রিন্ট করা
    for (int n : result) {
        std::cout << n << " "; // আউটপুট: 4 8
    }

    return 0;
}

এখানে std::list এর উপাদানগুলোর উপর transform এবং filter অপারেশন প্রয়োগ করা হয়েছে, যেখানে transform সবার মান দ্বিগুণ করে এবং filter কেবলমাত্র এমন মানগুলো রেখে দেয় যেগুলি 4 দিয়ে বিভাজ্য।


৩. Ranges with std::array

std::array একটি স্থির আকারের কনটেইনার যা C++11 এ পরিচিত। এটি ranges লাইব্রেরি ব্যবহার করার জন্য উপযুক্ত, বিশেষ করে যখন জানি যে আর্গুমেন্টের আকার পূর্বনির্ধারিত এবং স্থির।

উদাহরণ:

#include <iostream>
#include <array>
#include <ranges>

int main() {
    std::array<int, 5> arr = {1, 2, 3, 4, 5};

    // ranges লাইব্রেরির মাধ্যমে ট্রান্সফর্ম
    auto result = arr | std::ranges::views::transform([](int n) { return n * n; });

    // ফলাফল প্রিন্ট করা
    for (int n : result) {
        std::cout << n << " "; // আউটপুট: 1 4 9 16 25
    }

    return 0;
}

এখানে std::array এর উপর transform অপারেশন প্রয়োগ করা হয়েছে, যা প্রতিটি উপাদানকে তার বর্গফল হিসেবে রূপান্তরিত করে।


৪. Ranges with std::map

std::map হল একটি অ্যাসোসিয়েটিভ কনটেইনার যেখানে ডেটা কীগুলোর সাথে মান যুক্ত থাকে। Ranges লাইব্রেরি ব্যবহার করে এর উপাদানগুলোর উপর অপারেশনগুলো সহজে করা যায়।

উদাহরণ:

#include <iostream>
#include <map>
#include <ranges>

int main() {
    std::map<int, std::string> map = {{1, "One"}, {2, "Two"}, {3, "Three"}};

    // ranges এর মাধ্যমে কীগুলোর উপর কাজ করা
    auto result = map | std::ranges::views::transform([](auto& pair) { return pair.first; });

    // ফলাফল প্রিন্ট করা
    for (int key : result) {
        std::cout << key << " "; // আউটপুট: 1 2 3
    }

    return 0;
}

এখানে std::map এর কীগুলোর উপর transform অপারেশন প্রয়োগ করা হয়েছে, যা কেবলমাত্র কীগুলোকে রিটার্ন করছে।


Ranges এর সুবিধা

  1. স্মার্ট এবং পরিষ্কার কোড: Ranges লাইব্রেরি ব্যবহার করলে ডেটা ম্যানিপুলেশন এবং ট্রাভার্সাল সহজ, পরিষ্কার এবং কার্যকর হয়।
  2. Lazy Evaluation: Ranges এর অ্যালগরিদমগুলি লেজি উপায়ে কাজ করে, অর্থাৎ কাজগুলো কেবল তখনই সম্পন্ন হয় যখন তা ব্যবহৃত হয়।
  3. কনসোলিডেটেড অ্যালগরিদম: একাধিক অ্যালগরিদমকে একসাথে এক লাইন কোডে কম্পোজ করা যায়, যা কোডকে আরো সুন্দর এবং সহজ পাঠযোগ্য করে তোলে।
  4. বড় ডেটা সেটের জন্য কার্যকর: Ranges লাইব্রেরির অপারেশনগুলো বড় ডেটা সেটে কম্পিউটেশন কমায় কারণ এটি আংশিকভাবে ডেটা প্রক্রিয়া করে (lazy evaluation)।

সারাংশ

  • Ranges লাইব্রেরি সি++20 তে নতুন এবং শক্তিশালী একটি ফিচার যা কনটেইনারের উপাদানগুলোর উপর অ্যালগরিদম প্রয়োগকে আরও সহজ, পরিষ্কার এবং কার্যকরী করে।
  • এটি std::vector, std::list, std::array, std::map ইত্যাদি কনটেইনারের সাথে খুব সহজে কাজ করতে পারে।
  • Lazy evaluation এবং composition সুবিধা নিয়ে এটি ফাংশনাল প্রোগ্রামিং স্টাইলের কার্যকারিতা সি++ এ নিয়ে আসে।
Content added By
Promotion

Are you sure to start over?

Loading...