Skill

Functions এবং Methods (ফাংশন এবং মেথডস)

রাস্ট (Rust) - Computer Programming

375

ফাংশন (Functions)

ফাংশন হল একটি কোড ব্লক যা নির্দিষ্ট কাজ সম্পাদন করে এবং একটি নামের মাধ্যমে এক্সেস করা যায়। এটি আর্গুমেন্ট গ্রহণ করতে পারে এবং প্রয়োজনীয় ফলাফল রিটার্ন করতে পারে। রাস্টে ফাংশনগুলি খুবই শক্তিশালী এবং তাদের কাজের দক্ষতা নির্ভর করে তাদের ব্যবহৃত টাইপ এবং আর্গুমেন্টগুলির ওপর।

ফাংশন ডিফাইন করা

রাস্টে ফাংশন ডিফাইন করার জন্য fn কীওয়ার্ড ব্যবহার করা হয়। একটি সাধারণ ফাংশন আর্গুমেন্ট গ্রহণ করতে পারে এবং একটি ভ্যালু রিটার্ন করতে পারে।
উদাহরণ:

fn add(a: i32, b: i32) -> i32 {
    a + b
}

fn main() {
    let result = add(5, 3);
    println!("The sum is: {}", result);
}

এখানে add নামের একটি ফাংশন ডিফাইন করা হয়েছে, যা দুটি i32 টাইপের আর্গুমেন্ট গ্রহণ করে এবং তাদের যোগফল রিটার্ন করে।

ফাংশন রিটার্ন টাইপ

ফাংশনটি যে ধরনের মান রিটার্ন করবে, তা ডিফাইন করার জন্য -> চিহ্ন ব্যবহার করা হয়। এই চিহ্নের পরে টাইপ উল্লেখ করতে হয়। যদি ফাংশন কোনো মান রিটার্ন না করে, তাহলে () (unit type) ব্যবহার করা হয়।

উদাহরণ:

fn greet(name: &str) {
    println!("Hello, {}!", name);
}

এই ফাংশনটি কোনো মান রিটার্ন না করে, শুধু কনসোলে একটি বার্তা প্রিন্ট করে।


মেথডস (Methods)

রাস্টে মেথড হল একটি বিশেষ ধরনের ফাংশন যা একটি struct বা enum বা trait এর সাথে সম্পর্কিত থাকে। মেথডগুলোর প্রথম প্যারামিটারটি সাধারণত self থাকে, যা ইনস্ট্যান্স অবজেক্টকে নির্দেশ করে।

মেথড ডিফাইন করা

রাস্টে মেথড ডিফাইন করার জন্য impl (implementation) ব্লক ব্যবহার করা হয়। এই ব্লকটি একটি struct বা enum এর সাথে সম্পর্কিত মেথড ডিফাইন করতে সাহায্য করে।

উদাহরণ:

struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // একটি মেথড যা আয়তনের হিসাব করবে
    fn area(&self) -> u32 {
        self.width * self.height
    }
    
    // একটি মেথড যা আয়তনের সীমানা চেক করবে
    fn is_square(&self) -> bool {
        self.width == self.height
    }
}

fn main() {
    let rect = Rectangle {
        width: 30,
        height: 50,
    };
    
    println!("The area is: {}", rect.area()); // মেথড কল
    println!("Is it a square? {}", rect.is_square()); // মেথড কল
}

এখানে Rectangle নামের একটি struct রয়েছে, এবং এর জন্য দুটি মেথড ডিফাইন করা হয়েছে:

  • area যা আয়তন হিসাব করে।
  • is_square যা চেক করে, আয়তনের সীমানা সমান কিনা।

মেথডের প্রথম প্যারামিটার হিসেবে &self ব্যবহার করা হয়, যা struct বা enum এর বর্তমান অবস্থা (অবজেক্ট) কে রেফারেন্স করে।


ফাংশন এবং মেথডের মধ্যে পার্থক্য

  • ফাংশন: ফাংশন সাধারণত স্বাধীন হয় এবং কোনো অবজেক্টের সাথে সম্পর্কিত থাকে না। এটি যেকোনো ধরনের আর্গুমেন্ট গ্রহণ করে এবং একটি মান রিটার্ন করতে পারে।
  • মেথড: মেথড সর্বদা একটি struct, enum বা trait এর সাথে সম্পর্কিত থাকে এবং প্রথম প্যারামিটার হিসেবে self নেয়, যা মেথডটিকে একটি অবজেক্টের উপর কাজ করতে সক্ষম করে।

মেথড এবং ফাংশন এর মধ্যে সাদৃশ্য

  • উভয়ই আর্গুমেন্ট গ্রহণ করতে পারে এবং একটি মান রিটার্ন করতে পারে।
  • উভয়েই একে অপরের মতো ব্যবহৃত হয় এবং কোডের পুনঃব্যবহারযোগ্যতা ও কার্যকারিতা বাড়াতে সহায়তা করে।

সারাংশ

রাস্টে ফাংশন এবং মেথডস দুইটি গুরুত্বপূর্ণ ধারণা। ফাংশন সাধারণত স্বাধীনভাবে কাজ করে এবং নির্দিষ্ট কাজ সম্পাদন করে, जबकि মেথড একটি struct বা enum এর সাথে সম্পর্কিত থাকে এবং সে অনুযায়ী কাজ করে। রাস্টের এই দুটি বৈশিষ্ট্য কোডের পুনঃব্যবহারযোগ্যতা এবং গঠনশীলতা বৃদ্ধি করে।

Content added By

Functions কী?

ফাংশন একটি কোডের ব্লক যা একাধিক কাজ সম্পাদন করতে ব্যবহৃত হয়। ফাংশনের মূল উদ্দেশ্য হলো কোডের পুনঃব্যবহারযোগ্যতা বাড়ানো, কোডের পাঠযোগ্যতা উন্নত করা এবং কোডের জটিলতা কমানো। একটি ফাংশন নির্দিষ্ট ইনপুট নিয়ে কাজ করে এবং একটি আউটপুট ফেরত দেয়।

রাস্টে ফাংশন দুটি প্রধানভাবে ব্যবহৃত হয়:

  1. Function Declaration (ফাংশন ডিক্লারেশন)
  2. Function Usage (ফাংশন ব্যবহার)

১. ফাংশন ডিক্লারেশন (Function Declaration)

রাস্টে ফাংশন ডিক্লারেশন সাধারণত fn কীওয়ার্ড দিয়ে শুরু হয়। একটি ফাংশনের ডিক্লারেশনে ফাংশনের নাম, আর্গুমেন্ট এবং রিটার্ন টাইপ উল্লেখ করা হয়।

সিনট্যাক্স:

fn function_name(parameter1: type, parameter2: type) -> return_type {
    // function body
}
  • fn: ফাংশন ডিক্লারেশন শুরুর কীওয়ার্ড।
  • function_name: ফাংশনের নাম।
  • parameter: ফাংশনের ইনপুট (অথবা প্যারামিটার), যার একটি নির্দিষ্ট টাইপ থাকে।
  • -> return_type: ফাংশনের আউটপুট টাইপ, যদি আউটপুট থাকে।
  • {}: ফাংশনের বডি, যেখানে ফাংশনের কোড লেখা হয়।

উদাহরণ:

fn add(a: i32, b: i32) -> i32 {
    a + b
}

এখানে:

  • add ফাংশন দুটি পূর্ণসংখ্যা গ্রহণ করে এবং তাদের যোগফল প্রদান করে।

২. ফাংশন ব্যবহার (Function Usage)

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

সিনট্যাক্স:

function_name(argument1, argument2);

উদাহরণ:

fn main() {
    let result = add(5, 3);
    println!("The sum is: {}", result);
}

এখানে:

  • add(5, 3) ফাংশনকে কল করে দুটি ইনপুট ৫ এবং ৩ প্রদান করা হয়েছে। আউটপুট হিসেবে 8 ফেরত আসবে, যা result এ সংরক্ষিত হবে।
  • println! ম্যাক্রো আউটপুট প্রদর্শন করবে।

৩. ফাংশন রিটার্ন (Function Return)

রাস্টে একটি ফাংশন যদি কোনো আউটপুট ফেরত দিতে চায়, তবে -> return_type ব্যবহার করতে হয়। যদি ফাংশন কোনো মান ফেরত না দেয়, তবে তার রিটার্ন টাইপ () (unit type) হয়।

উদাহরণ:

fn greet(name: &str) -> String {
    format!("Hello, {}!", name)
}

fn main() {
    let greeting = greet("Alice");
    println!("{}", greeting);
}

এখানে:

  • greet ফাংশন একটি স্ট্রিং আর্গুমেন্ট গ্রহণ করে এবং একটি স্ট্রিং আউটপুট প্রদান করে।

৪. যদি রিটার্ন না থাকে (When No Return is Needed)

যদি ফাংশন থেকে কোনো রিটার্ন মানের প্রয়োজন না হয়, তবে () ব্যবহার করা হয়। এটি একটি বিশেষ টাইপ যা শুধুমাত্র ফাংশনের জন্য ব্যবহৃত হয় এবং তা unit type নামে পরিচিত।

উদাহরণ:

fn print_message() {
    println!("This is a simple message.");
}

fn main() {
    print_message();
}

এখানে:

  • print_message ফাংশনটি কোনো রিটার্ন মান ফেরত দেয় না, শুধু একটি মেসেজ প্রিন্ট করে।

৫. অপশনাল রিটার্ন (Optional Return)

রাস্টে একটি ফাংশন কিছু সময়ে আউটপুট না দিতে পারে। এই জন্য Option<T> ব্যবহার করা হয়, যা একটি ফাংশনকে Some(T) বা None ফেরত দিতে সক্ষম করে।

উদাহরণ:

fn divide(a: i32, b: i32) -> Option<i32> {
    if b == 0 {
        None
    } else {
        Some(a / b)
    }
}

fn main() {
    match divide(10, 2) {
        Some(result) => println!("The result is: {}", result),
        None => println!("Cannot divide by zero."),
    }
}

এখানে:

  • divide ফাংশনটি যদি b == 0 হয়, তবে None ফেরত দেয়, আর যদি না হয় তবে Some(a / b) ফেরত দেয়।

সারাংশ

ফাংশন রাস্টে কোডের পুনঃব্যবহারযোগ্যতা এবং সুসংগতি বৃদ্ধি করতে সহায়ক। রাস্টে ফাংশন ডিক্লারেশন এবং ব্যবহার খুবই সহজ এবং সুবিধাজনক। মেম্বার আর্গুমেন্ট, রিটার্ন টাইপ, এবং ফাংশন কলের মাধ্যমে কোডকে পরিষ্কার ও সংহত রাখা যায়। রাস্টের ফাংশন ব্যবহারের মাধ্যমে আপনি আরও কার্যকর এবং সুরক্ষিত কোড তৈরি করতে পারবেন।

Content added By

Parameters (প্যারামিটারস)

রাস্টে, ফাংশনের মাধ্যমে ডেটা স্থানান্তরের জন্য প্যারামিটার ব্যবহার করা হয়। প্যারামিটারগুলি ফাংশনের ইনপুট হিসেবে কাজ করে, যা ফাংশনের ভিতরে ব্যবহৃত হতে পারে।

১.১ প্যারামিটার ডিক্লারেশন

রাস্টে, প্যারামিটারগুলির জন্য ডেটা টাইপ নির্ধারণ করতে হয়। প্যারামিটারগুলো সাধারণত ফাংশন কলের মাধ্যমে আর্গুমেন্ট হিসেবে প্রদান করা হয়। রাস্টে প্যারামিটার পাস করার সময় আপনি ডেটা কীভাবে পাস করবেন তা নির্ধারণ করতে পারেন, যেমন By value (মুল্যে পাস), By reference (রেফারেন্স পাস), বা **By mutable reference (মিউটেবল রেফারেন্স পাস)**।

১.২ By Value (মুল্যে পাস)

ডিফল্টভাবে, রাস্ট প্যারামিটারগুলি By value পাস করে, অর্থাৎ ফাংশনের ভিতরে প্যারামিটারটির একটি কপি তৈরি হয়।

fn add(x: i32, y: i32) -> i32 {
    x + y
}

fn main() {
    let result = add(5, 10);
    println!("The result is: {}", result);
}

এখানে x এবং y প্যারামিটারগুলি By value পাস করা হয়েছে। ফাংশন কল করার সময়, এই প্যারামিটারগুলির কপি ফাংশনের মধ্যে পাঠানো হয়েছে।

১.৩ By Reference (রেফারেন্স পাস)

রাস্টে আপনি ডেটার মালিকানা না বদলিয়ে ফাংশনে রেফারেন্স পাস করতে পারেন। এটি বোরোউ (borrowing) সিস্টেমের মাধ্যমে করা হয়। রেফারেন্সের মাধ্যমে প্যারামিটার পাস করলে ডেটার কপি তৈরি হয় না এবং এটি আরও দক্ষ হতে পারে।

fn print_length(s: &String) {
    println!("The length of the string is: {}", s.len());
}

fn main() {
    let str = String::from("Hello, Rust!");
    print_length(&str);  // By reference
}

এখানে s প্যারামিটারটি By reference পাস করা হয়েছে, যার ফলে মূল ডেটার মালিকানা বজায় থাকে এবং ফাংশন শুধুমাত্র রেফারেন্স ব্যবহার করে ডেটার উপর কাজ করে।

১.৪ By Mutable Reference (মিউটেবল রেফারেন্স পাস)

রাস্টে আপনি mutable reference ব্যবহার করে ডেটাকে পরিবর্তন করতে পারেন, তবে এটি রেফারেন্স পাসের সময় প্রযোজ্য হতে হবে।

fn change_value(x: &mut i32) {
    *x += 1;
}

fn main() {
    let mut num = 10;
    change_value(&mut num);  // By mutable reference
    println!("The changed value is: {}", num);
}

এখানে x প্যারামিটারটি mutable reference পাস করা হয়েছে, যার মাধ্যমে আমরা মূল ভেরিয়েবলের মান পরিবর্তন করেছি।


Return Values (রিটার্ন ভ্যালুজ)

রাস্টে, ফাংশন থেকে একটি মান (value) ফেরত দেওয়ার জন্য return কিওয়ার্ড ব্যবহার করা হয়। ফাংশনটি একটি রিটার্ন টাইপ ডিফাইন করতে হয় যা তার আউটপুট হিসেবে প্রদান করা হবে।

২.১ একটি ভ্যালু রিটার্ন করা

রাস্টে, ফাংশন এক বা একাধিক মান রিটার্ন করতে পারে, এবং এটি return কিওয়ার্ড অথবা আউটপুট টাইপ দিয়ে করা হয়। তবে, রাস্টে একটি ফাংশন সবসময় একটি মান রিটার্ন করতে হবে, বিশেষত যদি তার রিটার্ন টাইপ ডিফাইন করা থাকে।

fn multiply(x: i32, y: i32) -> i32 {
    x * y
}

fn main() {
    let result = multiply(3, 4);
    println!("The result is: {}", result);
}

এখানে multiply ফাংশনটি দুটি i32 টাইপের প্যারামিটার নেয় এবং একটি i32 মান রিটার্ন করে।

২.২ অপশনাল রিটার্ন (Option Type)

কখনও কখনও ফাংশন এমন একটি মান রিটার্ন করতে পারে যা উপস্থিত না-ও থাকতে পারে (এটি NULL বা None হতে পারে)। এর জন্য, রাস্ট Option টাইপ ব্যবহার করে, যা একটি ফাংশন থেকে Some(T) বা None ফেরত দেয়।

fn find_max(a: i32, b: i32) -> Option<i32> {
    if a > b {
        Some(a)
    } else if b > a {
        Some(b)
    } else {
        None
    }
}

fn main() {
    let result = find_max(10, 20);
    match result {
        Some(val) => println!("The maximum value is: {}", val),
        None => println!("The values are equal."),
    }
}

এখানে find_max ফাংশনটি Option<i32> রিটার্ন করে, যেখানে Some(i32) ফেরত আসবে যদি দুটি মান আলাদা থাকে এবং None ফেরত আসবে যদি তারা সমান হয়।

২.৩ Return Without return Keyword

রাস্টে return কিওয়ার্ড ছাড়া একটি মানও রিটার্ন করা যেতে পারে। যদি ফাংশনের শেষে একটি এক্সপ্রেশন থাকে, তবে এটি রিটার্ন করা হবে।

fn add(x: i32, y: i32) -> i32 {
    x + y  // Implicit return, no need for the `return` keyword
}

fn main() {
    let result = add(5, 10);
    println!("The result is: {}", result);
}

এখানে x + y আউটপুটটি সরাসরি রিটার্ন হবে, এবং return কিওয়ার্ড ব্যবহার করার প্রয়োজন নেই।


সারাংশ

রাস্টে প্যারামিটার এবং রিটার্ন ভ্যালুজ ব্যবহারের মাধ্যমে ফাংশনের ইনপুট এবং আউটপুট পরিচালিত হয়। আপনি বিভিন্ন ধরনের প্যারামিটার পাস করতে পারেন যেমন By value, By reference, এবং By mutable reference। এছাড়াও, ফাংশন থেকে একটি মান ফেরত দিতে return কিওয়ার্ড বা সরাসরি এক্সপ্রেশন ব্যবহার করা যায়। রাস্টের শক্তিশালী মালিকানা এবং বোরোউ সিস্টেম এই ফাংশন ব্যবস্থাপনাকে আরও নিরাপদ এবং কার্যকরী করে তোলে।

Content added By

Methods (মেথডস)

রাস্টে মেথডস হল ফাংশনগুলো যা একটি স্ট্রাকচার (struct), এনাম (enum), অথবা ট্রেট (trait) এর সাথে যুক্ত থাকে। এই ফাংশনগুলো সাধারণত self প্যারামিটার ব্যবহার করে ডেটার উপর কাজ করে। self একটি অবজেক্টের মালিকানা বা রেফারেন্স হিসেবে কাজ করে, যা ফাংশনকে সেই অবজেক্টের ডেটা অ্যাক্সেস করার অনুমতি দেয়।

মেথডের সিঙ্কট্যাক্স:

মেথডের মধ্যে self ব্যবহৃত হয় যা অবজেক্টের ইনস্ট্যান্সের উপর কাজ করে।

উদাহরণ:

struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // একটি মেথড যা Rectangle এর ক্ষেত্রফল প্রদান করে
    fn area(&self) -> u32 {
        self.width * self.height
    }
    
    // একটি মেথড যা Rectangle এর বর্গাকার কিনা তা চেক করে
    fn is_square(&self) -> bool {
        self.width == self.height
    }
}

fn main() {
    let rect = Rectangle {
        width: 30,
        height: 30,
    };

    println!("Area: {}", rect.area()); // মেথড কল
    println!("Is square? {}", rect.is_square()); // মেথড কল
}

ব্যাখ্যা:

  • &self হচ্ছে একটি ইমিউটেবল রেফারেন্স যা অবজেক্টের ডেটা অ্যাক্সেস করে।
  • area() মেথড Rectangle এর ক্ষেত্রফল বের করে।
  • is_square() মেথড চেক করে যদি width এবং height সমান হয় তবে এটি সঠিকভাবে true রিটার্ন করবে।

Associated Functions (অ্যাসোসিয়েটেড ফাংশনস)

রাস্টে অ্যাসোসিয়েটেড ফাংশনস হল এমন ফাংশনগুলো যা একটি টাইপের সাথে যুক্ত থাকে, তবে সেগুলো কোনো ইনস্ট্যান্স ডেটা (অথবা অবজেক্টের মালিকানা) অ্যাক্সেস করে না। এই ফাংশনগুলো সাধারণত impl ব্লকের ভিতরে থাকে এবং self প্যারামিটার ব্যবহার না করে স্ট্যাটিক ফাংশন হিসেবে কাজ করে।

অ্যাসোসিয়েটেড ফাংশনস সাধারণত ফ্যাক্টরি ফাংশন হিসেবে ব্যবহৃত হয়, যেমন কোন নতুন অবজেক্ট তৈরি করা।

অ্যাসোসিয়েটেড ফাংশনের সিঙ্কট্যাক্স:

এগুলো self ছাড়া কল করা হয় এবং এই ফাংশনগুলো সাধারণত একটি টাইপের সাথে যুক্ত থাকে।

উদাহরণ:

struct Circle {
    radius: f64,
}

impl Circle {
    // একটি অ্যাসোসিয়েটেড ফাংশন যা একটি নতুন Circle তৈরি করে
    fn new(radius: f64) -> Circle {
        Circle { radius }
    }
    
    // একটি মেথড যা Circle এর ক্ষেত্রফল প্রদান করে
    fn area(&self) -> f64 {
        3.14 * self.radius * self.radius
    }
}

fn main() {
    let circle = Circle::new(10.0); // অ্যাসোসিয়েটেড ফাংশন কল
    println!("Area of the circle: {}", circle.area()); // মেথড কল
}

ব্যাখ্যা:

  • Circle::new(10.0) একটি অ্যাসোসিয়েটেড ফাংশন কল, যা একটি নতুন Circle অবজেক্ট তৈরি করে।
  • area() মেথড Circle এর ক্ষেত্রফল বের করে।

Methods vs Associated Functions

  • Methods: এই ফাংশনগুলো একটি অবজেক্টের উপর কাজ করে এবং সেগুলো self বা তার রেফারেন্স ব্যবহার করে।
  • Associated Functions: এই ফাংশনগুলো সাধারণত টাইপের সাথে যুক্ত থাকে এবং self ব্যবহারের প্রয়োজন হয় না, যেমন একটি নতুন অবজেক্ট তৈরি করা বা কোনো স্ট্যাটিক অপারেশন সম্পাদন করা।

সারাংশ:

  • Methods অবজেক্টের উপর কাজ করে এবং self ব্যবহারের মাধ্যমে ডেটাকে অ্যাক্সেস করে।
  • Associated Functions অবজেক্টের সাথে সম্পর্কিত ফাংশন, তবে এগুলো সাধারণত self ছাড়া কাজ করে এবং স্ট্যাটিক ফাংশন হিসেবেই ব্যবহৃত হয়।
Content added By

Closures (ক্লোজার)

রাস্টে Closures হল এমন ফাংশন যেগুলি তাদের চারপাশের পরিবেশ (environment) থেকে ভ্যালু বা ভেরিয়েবল ক্যাপচার করতে সক্ষম। এটি অন্য ফাংশন বা স্কোপের মধ্যে থাকা ভেরিয়েবলগুলিকে অন্তর্ভুক্ত করতে পারে এবং সেগুলিকে নিজেদের মধ্যে ব্যবহার করতে পারে।

ক্লোজারের মূল বৈশিষ্ট্য:

  • ক্লোজার একটি ফাংশন এবং সেই ফাংশনের বাইরের স্কোপের ভেরিয়েবলগুলির মধ্যে সম্পর্ক তৈরি করে।
  • ক্লোজার তাদের বাইরের ভেরিয়েবলগুলিকে borrow বা move করতে পারে।
  • ক্লোজার সাধারণত ফাংশন আর্গুমেন্ট হিসেবে ব্যবহৃত হয় এবং তাদের নিজস্ব স্টেট রাখতে পারে।

ক্লোজারের সিনট্যাক্স:

রাস্টে ক্লোজার ডিফাইন করার জন্য সাধারণত |parameters| expression সিনট্যাক্স ব্যবহার করা হয়।

উদাহরণ:

fn main() {
    let add = |a, b| a + b; // ক্লোজার যা দুইটি প্যারামিটার নেয় এবং তাদের যোগফল দেয়
    let result = add(5, 10);
    println!("Result: {}", result);
}

এখানে add হল একটি ক্লোজার যা দুইটি আর্গুমেন্ট নিয়ে তাদের যোগফল রিটার্ন করে। ক্লোজারটি |a, b| a + b আকারে সংজ্ঞায়িত হয়েছে, যেখানে a এবং b প্যারামিটার এবং a + b হল আউটপুট এক্সপ্রেশন।

ক্লোজার এবং সিস্টেমের স্টেট:

রাস্টে ক্লোজারের প্রধান সুবিধা হলো এটি তাদের বাইরের স্কোপ থেকে ভেরিয়েবল borrow করতে পারে অথবা সেগুলি move করতে পারে।

উদাহরণ (borrow):

fn main() {
    let x = 5;
    let print_x = || println!("x is {}", x); // borrow the value of x
    print_x(); // "x is 5"
}

এখানে x ক্লোজার দ্বারা borrow করা হয়েছে, এবং এটি ক্লোজারের মধ্যে ব্যবহৃত হয়েছে।

উদাহরণ (move):

fn main() {
    let x = vec![1, 2, 3];
    let take_ownership = move || println!("x is {:?}", x); // move x into the closure
    take_ownership(); // "x is [1, 2, 3]"
}

এখানে x ক্লোজারে move করা হয়েছে, অর্থাৎ এটি আর বাইরের স্কোপে অ্যাক্সেসযোগ্য নয়।


Higher-Order Functions (হায়ার-অর্ডার ফাংশন)

Higher-Order Functions হল এমন ফাংশন যা অন্য ফাংশনকে আর্গুমেন্ট হিসেবে গ্রহণ করতে পারে অথবা একটি ফাংশন রিটার্ন করতে পারে। এই ধরনের ফাংশন আমাদের কোড আরও আবস্ট্রাক্ট এবং রিইউজেবল করে তোলে।

হায়ার-অর্ডার ফাংশনের বৈশিষ্ট্য:

  • একটি হায়ার-অর্ডার ফাংশন অন্য একটি ফাংশনকে আর্গুমেন্ট হিসেবে গ্রহণ করতে পারে।
  • এটি একটি ফাংশন রিটার্নও করতে পারে।

উদাহরণ:

fn apply<F>(f: F) 
where
    F: Fn() -> i32,
{
    println!("Result: {}", f());
}

fn main() {
    let x = || 5; // ক্লোজার যে ৫ রিটার্ন করে
    apply(x); // apply ফাংশনকে x ক্লোজার আর্গুমেন্ট হিসেবে প্রদান
}

এখানে apply একটি হায়ার-অর্ডার ফাংশন যা একটি ক্লোজার বা ফাংশনকে আর্গুমেন্ট হিসেবে গ্রহণ করছে এবং সেটি f() কল করে রিটার্ন ভ্যালু প্রদর্শন করছে।

আরও উদাহরণ:

fn add_one(x: i32) -> i32 {
    x + 1
}

fn apply_fn<F>(f: F, value: i32) -> i32 
where
    F: Fn(i32) -> i32,
{
    f(value)
}

fn main() {
    let result = apply_fn(add_one, 5); // add_one ফাংশনকে apply_fn এ আর্গুমেন্ট হিসেবে দেয়া
    println!("Result: {}", result); // Output: 6
}

এখানে apply_fn একটি হায়ার-অর্ডার ফাংশন যা add_one ফাংশনটিকে আর্গুমেন্ট হিসেবে গ্রহণ করছে এবং তাকে প্রয়োগ করে ফলাফল রিটার্ন করছে।


Closures এবং Higher-Order Functions এর মধ্যে সম্পর্ক

ক্লোজার এবং হায়ার-অর্ডার ফাংশন একে অপরের সাথে ঘনিষ্ঠভাবে সম্পর্কিত। ক্লোজারগুলো সাধারণত হায়ার-অর্ডার ফাংশনের আর্গুমেন্ট হিসেবে ব্যবহৃত হয়, এবং হায়ার-অর্ডার ফাংশন ক্লোজারগুলিকে সিস্টেমের ভেরিয়েবলগুলির সাথে ব্যবহার করতে সাহায্য করে।

উদাহরণ:

fn apply_closure<F>(f: F)
where
    F: Fn(),
{
    f();
}

fn main() {
    let closure = || println!("Hello from closure!"); // ক্লোজার
    apply_closure(closure); // হায়ার-অর্ডার ফাংশনে ক্লোজার পাস করা
}

এখানে apply_closure একটি হায়ার-অর্ডার ফাংশন যা একটি ক্লোজার আর্গুমেন্ট হিসেবে গ্রহণ করছে এবং সেটি কল করে।


সারাংশ

  • Closures হল এমন ফাংশন যা বাইরের স্কোপের ভেরিয়েবলগুলিকে borrow বা move করতে পারে, যা কোডের পুনঃব্যবহারযোগ্যতা এবং কোডকে আরো কমপ্যাক্ট করে তোলে।
  • Higher-Order Functions হল এমন ফাংশন যা অন্য ফাংশন বা ক্লোজারকে আর্গুমেন্ট হিসেবে গ্রহণ করতে পারে অথবা একটি ফাংশন রিটার্ন করতে পারে, এবং এটি আমাদের কোডের অবস্ট্রাকশন এবং পুনঃব্যবহারযোগ্যতা বৃদ্ধি করে।

রাস্টে ক্লোজার এবং হায়ার-অর্ডার ফাংশন প্রোগ্রামিংয়ের ক্ষমতা এবং সৌন্দর্য বাড়ায়, কারণ এগুলি কোডকে আরও পরিষ্কার এবং ম্যানেজেবল করে তোলে।

Content added By
Promotion

Are you sure to start over?

Loading...