কন্ট্রোল ফ্লো (Control Flow)

কোনো শর্ত true কিনা তার উপর নির্ভর করে কিছু কোড চালানোর ক্ষমতা এবং একটি শর্ত true থাকা অবস্থায় কিছু কোড বারবার চালানোর ক্ষমতা বেশিরভাগ প্রোগ্রামিং ভাষার মৌলিক বিল্ডিং ব্লক। Rust কোডের এক্সিকিউশনের ফ্লো নিয়ন্ত্রণ করার জন্য সবচেয়ে সাধারণ যে কনস্ট্রাক্টগুলো ব্যবহার করা হয় সেগুলো হল if এক্সপ্রেশন এবং লুপ।

if এক্সপ্রেশন (if Expressions)

একটি if এক্সপ্রেশন আপনাকে শর্তের উপর নির্ভর করে আপনার কোডকে শাখা (branch) করতে দেয়। আপনি একটি শর্ত দেন এবং তারপর বলেন, “যদি এই শর্তটি পূরণ হয়, তাহলে কোডের এই ব্লকটি চালাও। যদি শর্তটি পূরণ না হয়, তাহলে কোডের এই ব্লকটি চালিও না।”

if এক্সপ্রেশনটি আরও ভালোভাবে বোঝার জন্য আপনার projects ডিরেক্টরিতে branches নামে একটি নতুন প্রোজেক্ট তৈরি করুন। src/main.rs ফাইলে, নিম্নলিখিতটি ইনপুট দিন:

Filename: src/main.rs

fn main() { let number = 3; if number < 5 { println!("condition was true"); } else { println!("condition was false"); } }

সমস্ত if এক্সপ্রেশন if কীওয়ার্ড দিয়ে শুরু হয়, তারপরে একটি শর্ত থাকে। এই ক্ষেত্রে, শর্তটি পরীক্ষা করে যে number ভেরিয়েবলের মান 5-এর কম কিনা। শর্তটি যদি true হয় তাহলে যে কোড ব্লকটি চালাতে হবে সেটি আমরা শর্তের ঠিক পরেই কার্লি ব্র্যাকেটের ভিতরে রাখি। if এক্সপ্রেশনের শর্তগুলোর সাথে সম্পর্কিত কোডের ব্লকগুলোকে কখনও কখনও আর্মস (arms) বলা হয়, ঠিক যেমনটি আমরা চ্যাপ্টার ২-এর “অনুমানের সাথে গোপন সংখ্যার তুলনা করা” বিভাগে আলোচনা করা match এক্সপ্রেশনের আর্মগুলোর মতো।

ঐচ্ছিকভাবে, আমরা একটি else এক্সপ্রেশনও অন্তর্ভুক্ত করতে পারি, যেটি আমরা এখানে করেছি, যদি শর্তটি false হয় তবে প্রোগ্রামটিকে চালানোর জন্য একটি বিকল্প কোড ব্লক দিতে। আপনি যদি একটি else এক্সপ্রেশন সরবরাহ না করেন এবং শর্তটি false হয়, তাহলে প্রোগ্রামটি কেবল if ব্লকটি এড়িয়ে যাবে এবং কোডের পরবর্তী অংশে চলে যাবে।

এই কোডটি চালানোর চেষ্টা করুন; আপনার নিম্নলিখিত আউটপুট দেখা উচিত:

$ cargo run Compiling branches v0.1.0 (file:///projects/branches) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s Running `target/debug/branches` condition was true

চলুন number-এর মান এমন একটি মানে পরিবর্তন করার চেষ্টা করি যা শর্তটিকে false করে, কী ঘটে তা দেখার জন্য:

fn main() { let number = 7; if number < 5 { println!("condition was true"); } else { println!("condition was false"); } }

প্রোগ্রামটি আবার চালান এবং আউটপুট দেখুন:

$ cargo run Compiling branches v0.1.0 (file:///projects/branches) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s Running `target/debug/branches` condition was false

এটিও লক্ষ্য করার মতো যে এই কোডের শর্তটি অবশ্যই একটি bool হতে হবে। শর্তটি যদি bool না হয়, তাহলে আমরা একটি এরর পাব। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি চালানোর চেষ্টা করুন:

Filename: src/main.rs

fn main() { let number = 3; if number { println!("number was three"); } }

if শর্তটি এবার 3 মান মূল্যায়ন করে এবং Rust একটি এরর দেয়:

$ cargo run Compiling branches v0.1.0 (file:///projects/branches) error[E0308]: mismatched types --> src/main.rs:4:8 | 4 | if number { | ^^^^^^ expected `bool`, found integer For more information about this error, try `rustc --explain E0308`. error: could not compile `branches` (bin "branches") due to 1 previous error

এররটি নির্দেশ করে যে Rust একটি bool আশা করেছিল কিন্তু একটি ইন্টিজার পেয়েছে। Ruby এবং JavaScript-এর মতো ভাষাগুলোর বিপরীতে, Rust স্বয়ংক্রিয়ভাবে নন-বুলিয়ান টাইপগুলোকে বুলিয়ানে রূপান্তর করার চেষ্টা করবে না। আপনাকে স্পষ্ট হতে হবে এবং সর্বদাই if-কে এর শর্ত হিসাবে একটি বুলিয়ান দিতে হবে। উদাহরণস্বরূপ, যদি আমরা চাই যে if কোড ব্লকটি তখনই চলুক যখন একটি সংখ্যা 0-এর সমান না হয়, তাহলে আমরা if এক্সপ্রেশনটিকে নিম্নলিখিতভাবে পরিবর্তন করতে পারি:

Filename: src/main.rs

fn main() { let number = 3; if number != 0 { println!("number was something other than zero"); } }

এই কোডটি চালালে number was something other than zero প্রিন্ট হবে।

else if দিয়ে একাধিক শর্ত হ্যান্ডেল করা (Handling Multiple Conditions with else if)

আপনি else if এক্সপ্রেশনে if এবং else একত্রিত করে একাধিক শর্ত ব্যবহার করতে পারেন। উদাহরণস্বরূপ:

Filename: src/main.rs

fn main() { let number = 6; if number % 4 == 0 { println!("number is divisible by 4"); } else if number % 3 == 0 { println!("number is divisible by 3"); } else if number % 2 == 0 { println!("number is divisible by 2"); } else { println!("number is not divisible by 4, 3, or 2"); } }

এই প্রোগ্রামটির চারটি সম্ভাব্য পথ রয়েছে যা এটি নিতে পারে। এটি চালানোর পরে, আপনার নিম্নলিখিত আউটপুট দেখা উচিত:

$ cargo run Compiling branches v0.1.0 (file:///projects/branches) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s Running `target/debug/branches` number is divisible by 3

যখন এই প্রোগ্রামটি এক্সিকিউট হয়, তখন এটি প্রতিটি if এক্সপ্রেশন পরীক্ষা করে এবং প্রথম বডিটি এক্সিকিউট করে যার শর্তটি true তে মূল্যায়ন করে। লক্ষ্য করুন যে 6, 2 দ্বারা বিভাজ্য হওয়া সত্ত্বেও, আমরা number is divisible by 2 আউটপুট দেখতে পাই না, বা আমরা else ব্লক থেকে number is not divisible by 4, 3, or 2 টেক্সটটিও দেখতে পাই না। কারণ হল Rust শুধুমাত্র প্রথম true শর্তের জন্য ব্লকটি এক্সিকিউট করে এবং একবার এটি একটি খুঁজে পেলে, এটি বাকিগুলোও পরীক্ষা করে না।

অত্যধিক else if এক্সপ্রেশন ব্যবহার করলে আপনার কোড এলোমেলো হয়ে যেতে পারে, তাই আপনার যদি একের বেশি থাকে, তাহলে আপনি হয়তো আপনার কোড রিফ্যাক্টর করতে চাইতে পারেন। এই ক্ষেত্রগুলোর জন্য চ্যাপ্টার ৬-এ match নামক একটি শক্তিশালী Rust ব্রাঞ্চিং কনস্ট্রাক্ট বর্ণনা করা হয়েছে।

let স্টেটমেন্টে if ব্যবহার করা (Using if in a let Statement)

যেহেতু if একটি এক্সপ্রেশন, তাই আমরা এটিকে একটি let স্টেটমেন্টের ডান পাশে ব্যবহার করতে পারি, ফলাফলটিকে একটি ভেরিয়েবলের সাথে অ্যাসাইন করতে, যেমনটি Listing 3-2-তে রয়েছে।

fn main() { let condition = true; let number = if condition { 5 } else { 6 }; println!("The value of number is: {number}"); }

number ভেরিয়েবলটি if এক্সপ্রেশনের ফলাফলের উপর ভিত্তি করে একটি মানের সাথে বাইন্ড করা হবে। কী ঘটে তা দেখতে এই কোডটি চালান:

$ cargo run Compiling branches v0.1.0 (file:///projects/branches) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.30s Running `target/debug/branches` The value of number is: 5

মনে রাখবেন যে কোডের ব্লকগুলো তাদের ভেতরের শেষ এক্সপ্রেশনটিতে মূল্যায়ন করে এবং সংখ্যাগুলোও নিজে থেকে এক্সপ্রেশন। এই ক্ষেত্রে, সম্পূর্ণ if এক্সপ্রেশনের মান নির্ভর করে কোন কোড ব্লকটি এক্সিকিউট হয় তার উপর। এর মানে হল if-এর প্রতিটি আর্ম (arm) থেকে ফলাফলের সম্ভাব্য মানগুলো অবশ্যই একই টাইপের হতে হবে; Listing 3-2-তে, if আর্ম এবং else আর্ম উভয়ের ফলাফলই ছিল i32 ইন্টিজার। যদি টাইপগুলো মেলানো না থাকে, যেমনটি নিম্নলিখিত উদাহরণে রয়েছে, তাহলে আমরা একটি এরর পাব:

Filename: src/main.rs

fn main() { let condition = true; let number = if condition { 5 } else { "six" }; println!("The value of number is: {number}"); }

আমরা যখন এই কোডটি কম্পাইল করার চেষ্টা করি, তখন আমরা একটি এরর পাব। if এবং else আর্মগুলোর মান টাইপগুলো অসঙ্গতিপূর্ণ, এবং Rust ঠিক কোথায় সমস্যাটি খুঁজে বের করতে হবে তা নির্দেশ করে:

$ cargo run Compiling branches v0.1.0 (file:///projects/branches) error[E0308]: `if` and `else` have incompatible types --> src/main.rs:4:44 | 4 | let number = if condition { 5 } else { "six" }; | - ^^^^^ expected integer, found `&str` | | | expected because of this For more information about this error, try `rustc --explain E0308`. error: could not compile `branches` (bin "branches") due to 1 previous error

if ব্লকের এক্সপ্রেশনটি একটি ইন্টিজারে মূল্যায়ন করে এবং else ব্লকের এক্সপ্রেশনটি একটি স্ট্রিংয়ে মূল্যায়ন করে। এটি কাজ করবে না কারণ ভেরিয়েবলগুলোর অবশ্যই একটি একক টাইপ থাকতে হবে এবং Rust-কে কম্পাইল করার সময় নিশ্চিতভাবে জানতে হবে যে number ভেরিয়েবলটির টাইপ কী। number-এর টাইপ জানা কম্পাইলারকে আমরা যেখানেই number ব্যবহার করি সেখানেই টাইপটি বৈধ কিনা তা যাচাই করতে দেয়। Rust সেটি করতে সক্ষম হবে না যদি number-এর টাইপ শুধুমাত্র রানটাইমে নির্ধারিত হত; কম্পাইলার আরও জটিল হবে এবং কোড সম্পর্কে কম গ্যারান্টি দিতে পারবে যদি এটিকে কোনো ভেরিয়েবলের জন্য একাধিক কাল্পনিক টাইপ ট্র্যাক রাখতে হত।

লুপের সাহায্যে পুনরাবৃত্তি (Repetition with Loops)

প্রায়শই কোডের একটি ব্লক একাধিকবার চালানো দরকারি। এই কাজের জন্য, Rust-এ বেশ কয়েকটি লুপ (loops) রয়েছে, যেগুলো লুপ বডির ভেতরের কোড শেষ পর্যন্ত চালাবে এবং তারপর অবিলম্বে আবার শুরুতে ফিরে যাবে। লুপ নিয়ে পরীক্ষা করার জন্য, আসুন loops নামে একটি নতুন প্রোজেক্ট তৈরি করি।

Rust-এ তিন ধরনের লুপ রয়েছে: loop, while, এবং for। চলুন প্রতিটি ব্যবহার করে দেখি।

loop দিয়ে কোড পুনরাবৃত্তি করা (Repeating Code with loop)

loop কীওয়ার্ডটি Rust-কে কোডের একটি ব্লক বারবার চালানোর নির্দেশ দেয়, যতক্ষণ না আপনি স্পষ্টতই এটিকে থামতে বলেন।

উদাহরণস্বরূপ, আপনার loops ডিরেক্টরির src/main.rs ফাইলটিকে নিচের মতো পরিবর্তন করুন:

Filename: src/main.rs

fn main() { loop { println!("again!"); } }

আমরা যখন এই প্রোগ্রামটি চালাই, তখন আমরা again! লেখাটি বারবার প্রিন্ট হতে দেখব যতক্ষণ না আমরা ম্যানুয়ালি প্রোগ্রামটি বন্ধ করি। বেশিরভাগ টার্মিনাল একটি ক্রমাগত লুপে আটকে থাকা একটি প্রোগ্রামকে বাধা দেওয়ার জন্য কীবোর্ড শর্টকাট ctrl-c সমর্থন করে। চেষ্টা করে দেখুন:

$ cargo run Compiling loops v0.1.0 (file:///projects/loops) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.08s Running `target/debug/loops` again! again! again! again! ^Cagain!

^C প্রতীকটি উপস্থাপন করে যেখানে আপনি ctrl-c টিপেছেন। আপনি ^C-এর পরে again! শব্দটি প্রিন্ট করা দেখতে পারেন বা নাও পারেন, এটি নির্ভর করে যে কোডটি লুপের কোথায় ছিল যখন এটি বাধার সংকেত পেয়েছিল।

সৌভাগ্যবশত, Rust কোড ব্যবহার করে একটি লুপ থেকে বেরিয়ে আসার একটি উপায়ও সরবরাহ করে। আপনি লুপের মধ্যে break কীওয়ার্ডটি রাখতে পারেন, প্রোগ্রামটিকে কখন লুপ চালানো বন্ধ করতে হবে তা বলার জন্য। মনে করে দেখুন যে, আমরা চ্যাপ্টার ২-এর “সঠিক অনুমানের পরে বন্ধ হওয়া” বিভাগে অনুমান করার গেমে এটি করেছিলাম, যখন ব্যবহারকারী সঠিক সংখ্যা অনুমান করে গেমটি জিতেছিলেন তখন প্রোগ্রামটি বন্ধ করার জন্য।

আমরা অনুমান করার গেমে continue ব্যবহার করেছি, যা একটি লুপের মধ্যে প্রোগ্রামটিকে সেই পুনরাবৃত্তির (iteration) অবশিষ্ট কোডগুলো এড়িয়ে যেতে এবং পরবর্তী পুনরাবৃত্তিতে যেতে বলে।

লুপ থেকে মান রিটার্ন করা (Returning Values from Loops)

loop-এর একটি ব্যবহার হল এমন একটি অপারেশন পুনরায় চেষ্টা করা যা আপনি জানেন যে ব্যর্থ হতে পারে, যেমন একটি থ্রেড তার কাজ সম্পন্ন করেছে কিনা তা পরীক্ষা করা। আপনাকে সেই অপারেশনের ফলাফল লুপের বাইরে আপনার কোডের বাকি অংশে পাস করতে হতে পারে। এটি করার জন্য, আপনি লুপ বন্ধ করার জন্য ব্যবহৃত break এক্সপ্রেশনের পরে যে মানটি রিটার্ন করতে চান সেটি যোগ করতে পারেন; সেই মানটি লুপ থেকে রিটার্ন করা হবে যাতে আপনি এটি ব্যবহার করতে পারেন, যেমনটি এখানে দেখানো হয়েছে:

fn main() { let mut counter = 0; let result = loop { counter += 1; if counter == 10 { break counter * 2; } }; println!("The result is {result}"); }

লুপের আগে, আমরা counter নামে একটি ভেরিয়েবল ঘোষণা করি এবং এটিকে 0 দিয়ে ইনিশিয়ালাইজ করি। তারপর আমরা লুপ থেকে রিটার্ন করা মান রাখার জন্য result নামে একটি ভেরিয়েবল ঘোষণা করি। লুপের প্রতিটি পুনরাবৃত্তিতে, আমরা counter ভেরিয়েবলে 1 যোগ করি এবং তারপর পরীক্ষা করি যে counter 10-এর সমান কিনা। যখন এটি হয়, তখন আমরা counter * 2 মান সহ break কীওয়ার্ডটি ব্যবহার করি। লুপের পরে, আমরা result-এ মান অ্যাসাইন করা স্টেটমেন্টটি শেষ করতে একটি সেমিকোলন ব্যবহার করি। অবশেষে, আমরা result-এর মান প্রিন্ট করি, যা এই ক্ষেত্রে 20

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

একাধিক লুপের মধ্যে পার্থক্য করার জন্য লুপ লেবেল (Loop Labels to Disambiguate Between Multiple Loops)

যদি আপনার লুপের মধ্যে লুপ থাকে, তাহলে break এবং continue সেই সময়ে সবচেয়ে ভেতরের লুপে প্রযোজ্য হয়। আপনি ঐচ্ছিকভাবে একটি লুপে একটি লুপ লেবেল নির্দিষ্ট করতে পারেন যা আপনি তারপর break বা continue-এর সাথে ব্যবহার করতে পারেন, যাতে সেই কীওয়ার্ডগুলো সবচেয়ে ভেতরের লুপের পরিবর্তে লেবেলযুক্ত লুপে প্রযোজ্য হয় তা নির্দিষ্ট করতে। লুপ লেবেলগুলো অবশ্যই একটি সিঙ্গেল কোট দিয়ে শুরু হতে হবে। দুটি নেস্টেড লুপ সহ এখানে একটি উদাহরণ দেওয়া হল:

fn main() { let mut count = 0; 'counting_up: loop { println!("count = {count}"); let mut remaining = 10; loop { println!("remaining = {remaining}"); if remaining == 9 { break; } if count == 2 { break 'counting_up; } remaining -= 1; } count += 1; } println!("End count = {count}"); }

বাইরের লুপটির লেবেল হল 'counting_up, এবং এটি 0 থেকে 2 পর্যন্ত গণনা করবে। লেবেল ছাড়া ভেতরের লুপটি 10 থেকে 9 পর্যন্ত গণনা করবে। প্রথম break যেটি একটি লেবেল নির্দিষ্ট করে না সেটি শুধুমাত্র ভেতরের লুপ থেকে বেরিয়ে আসবে। break 'counting_up; স্টেটমেন্টটি বাইরের লুপ থেকে বেরিয়ে আসবে। এই কোডটি প্রিন্ট করে:

$ cargo run Compiling loops v0.1.0 (file:///projects/loops) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.58s Running `target/debug/loops` count = 0 remaining = 10 remaining = 9 count = 1 remaining = 10 remaining = 9 count = 2 remaining = 10 End count = 2

while দিয়ে শর্তসাপেক্ষ লুপ (Conditional Loops with while)

একটি প্রোগ্রামের প্রায়শই একটি লুপের মধ্যে একটি শর্ত মূল্যায়ন করার প্রয়োজন হয়। যখন শর্তটি true হয়, তখন লুপটি চলে। যখন শর্তটি আর true থাকে না, তখন প্রোগ্রামটি break কল করে, লুপটি বন্ধ করে। loop, if, else, এবং break-এর সমন্বয় ব্যবহার করে এইরকম আচরণ বাস্তবায়ন করা সম্ভব; আপনি চাইলে এখনই একটি প্রোগ্রামে সেটি চেষ্টা করতে পারেন। তবে, এই প্যাটার্নটি এতটাই সাধারণ যে Rust-এর এর জন্য একটি বিল্ট-ইন ল্যাঙ্গুয়েজ কনস্ট্রাক্ট রয়েছে, যাকে while লুপ বলা হয়। Listing 3-3-তে, আমরা প্রোগ্রামটিকে তিনবার লুপ করতে, প্রতিবার কাউন্ট ডাউন করতে এবং তারপর লুপের পরে একটি মেসেজ প্রিন্ট করে প্রস্থান করতে while ব্যবহার করি।

fn main() { let mut number = 3; while number != 0 { println!("{number}!"); number -= 1; } println!("LIFTOFF!!!"); }

এই কনস্ট্রাক্টটি loop, if, else, এবং break ব্যবহার করলে প্রয়োজনীয় অনেক নেস্টিং দূর করে এবং এটি আরও সুস্পষ্ট। যখন একটি শর্ত true তে মূল্যায়ন করে, তখন কোডটি চলে; অন্যথায়, এটি লুপ থেকে বেরিয়ে যায়।

for দিয়ে একটি কালেকশনের মধ্যে লুপ করা (Looping Through a Collection with for)

আপনি একটি কালেকশনের উপাদানগুলোর ওপর লুপ করার জন্য while কনস্ট্রাক্টটিও ব্যবহার করতে পারেন, যেমন একটি অ্যারে। উদাহরণস্বরূপ, Listing 3-4-এর লুপটি অ্যারে a-এর প্রতিটি উপাদান প্রিন্ট করে।

fn main() { let a = [10, 20, 30, 40, 50]; let mut index = 0; while index < 5 { println!("the value is: {}", a[index]); index += 1; } }

এখানে, কোডটি অ্যারের উপাদানগুলোর মধ্যে গণনা করে। এটি ইনডেক্স 0 থেকে শুরু হয় এবং তারপর লুপটি অ্যারের শেষ ইনডেক্সে পৌঁছানো পর্যন্ত চলতে থাকে (অর্থাৎ, যখন index < 5 আর true থাকে না)। এই কোডটি চালালে অ্যারের প্রতিটি উপাদান প্রিন্ট হবে:

$ cargo run Compiling loops v0.1.0 (file:///projects/loops) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.32s Running `target/debug/loops` the value is: 10 the value is: 20 the value is: 30 the value is: 40 the value is: 50

প্রত্যাশিতভাবে, অ্যারের পাঁচটি মানই টার্মিনালে প্রদর্শিত হয়। যদিও index কোনো এক সময়ে 5 মানে পৌঁছাবে, লুপটি অ্যারে থেকে ষষ্ঠ মান আনার চেষ্টা করার আগেই চালানো বন্ধ করে দেয়।

তবে, এই পদ্ধতিটি এরর-প্রবণ; ইনডেক্স মান বা পরীক্ষার শর্তটি ভুল হলে আমরা প্রোগ্রামটিকে প্যানিক করাতে পারি। উদাহরণস্বরূপ, আপনি যদি a অ্যারের সংজ্ঞাকে চারটি উপাদান রাখার জন্য পরিবর্তন করেন কিন্তু শর্তটিকে while index < 4-এ আপডেট করতে ভুলে যান, তাহলে কোডটি প্যানিক করবে। এটি ধীরও, কারণ কম্পাইলার রানটাইম কোড যোগ করে, লুপের প্রতিটি পুনরাবৃত্তিতে ইনডেক্সটি অ্যারের সীমার মধ্যে আছে কিনা তার শর্তসাপেক্ষ পরীক্ষা করতে।

আরও সংক্ষিপ্ত বিকল্প হিসাবে, আপনি একটি for লুপ ব্যবহার করতে পারেন এবং একটি কালেকশনের প্রতিটি আইটেমের জন্য কিছু কোড চালাতে পারেন। একটি for লুপ Listing 3-5-এর কোডের মতো দেখায়।

fn main() { let a = [10, 20, 30, 40, 50]; for element in a { println!("the value is: {element}"); } }

আমরা যখন এই কোডটি চালাই, তখন আমরা Listing 3-4-এর মতোই একই আউটপুট দেখতে পাব। আরও গুরুত্বপূর্ণভাবে, আমরা এখন কোডের নিরাপত্তা বাড়িয়েছি এবং বাগের সম্ভাবনা দূর করেছি যা অ্যারের শেষের বাইরে যাওয়া বা যথেষ্ট দূরে না যাওয়া এবং কিছু আইটেম মিস করার ফলে হতে পারে।

for লুপ ব্যবহার করলে, আপনি যদি অ্যারের মানের সংখ্যা পরিবর্তন করেন তবে আপনাকে অন্য কোনো কোড পরিবর্তন করতে মনে রাখতে হবে না, যেমনটি Listing 3-4-এ ব্যবহৃত পদ্ধতির সাথে করতে হত।

for লুপগুলোর নিরাপত্তা এবং সংক্ষিপ্ততা সেগুলোকে Rust-এ সর্বাধিক ব্যবহৃত লুপ কনস্ট্রাক্ট করে তোলে। এমনকী যে পরিস্থিতিতে আপনি কিছু কোড একটি নির্দিষ্ট সংখ্যক বার চালাতে চান, যেমন কাউন্টডাউন উদাহরণ যা Listing 3-3-তে একটি while লুপ ব্যবহার করেছে, বেশিরভাগ Rustacean-রা একটি for লুপ ব্যবহার করবে। সেটি করার উপায় হল একটি Range ব্যবহার করা, যা স্ট্যান্ডার্ড লাইব্রেরি দ্বারা সরবরাহ করা হয়, যা একটি সংখ্যা থেকে শুরু করে অন্য সংখ্যার আগে শেষ হওয়া সমস্ত সংখ্যা ক্রমানুসারে তৈরি করে।

এখানে for লুপ এবং আরেকটি মেথড যা আমরা এখনও আলোচনা করিনি, rev, রেঞ্জটিকে বিপরীত করতে ব্যবহার করে কাউন্টডাউনটি দেখতে কেমন হবে:

Filename: src/main.rs

fn main() { for number in (1..4).rev() { println!("{number}!"); } println!("LIFTOFF!!!"); }

এই কোডটি একটু সুন্দর, তাই না?

সারসংক্ষেপ (Summary)

আপনি পেরেছেন! এটি একটি বড় চ্যাপ্টার ছিল: আপনি ভেরিয়েবল, স্কেলার এবং কম্পাউন্ড ডেটা টাইপ, ফাংশন, কমেন্ট, if এক্সপ্রেশন এবং লুপ সম্পর্কে শিখেছেন! এই চ্যাপ্টারে আলোচিত কনসেপ্টগুলো অনুশীলন করতে, নিম্নলিখিতগুলো করার জন্য প্রোগ্রাম তৈরি করার চেষ্টা করুন:

  • ফারেনহাইট এবং সেলসিয়াসের মধ্যে তাপমাত্রা রূপান্তর করুন।
  • nতম ফিবোনাচ্চি সংখ্যা তৈরি করুন।
  • "The Twelve Days of Christmas" ক্রিসমাস ক্যারোলের লিরিকগুলো প্রিন্ট করুন, গানের পুনরাবৃত্তির সুবিধা নিন।

আপনি যখন આગળ (গুজরাটি শব্দ, অর্থ 'move on') বাড়াতে প্রস্তুত হবেন, তখন আমরা Rust-এর একটি কনসেপ্ট নিয়ে আলোচনা করব যা অন্যান্য প্রোগ্রামিং ল্যাঙ্গুয়েজে সাধারণত থাকে না: ওনারশিপ (ownership)।