কন্ট্রোল ফ্লো (Control Flow)
একটি শর্ত true হলে কিছু কোড চালানো এবং একটি শর্ত true থাকা অবস্থায় কিছু কোড বারবার চালানোর ক্ষমতা বেশিরভাগ প্রোগ্রামিং ভাষার মৌলিক ভিত্তি। রাস্ট কোডের এক্সিকিউশন ফ্লো নিয়ন্ত্রণ করার জন্য সবচেয়ে সাধারণ কনস্ট্রাক্টগুলো হল if এক্সপ্রেশন এবং লুপ।
if এক্সপ্রেশন (if Expressions)
একটি if এক্সপ্রেশন আপনাকে শর্তের উপর ভিত্তি করে আপনার কোডকে বিভিন্ন শাখায় বিভক্ত করার সুযোগ দেয়। আপনি একটি শর্ত প্রদান করেন এবং তারপর বলেন, "যদি এই শর্তটি পূরণ হয়, তবে এই কোড ব্লকটি চালান। যদি শর্তটি পূরণ না হয়, তবে এই কোড ব্লকটি চালাবেন না।"
if এক্সপ্রেশন অন্বেষণ করতে আপনার projects ডিরেক্টরিতে branches নামে একটি নতুন প্রজেক্ট তৈরি করুন। src/main.rs ফাইলে, নিম্নলিখিতটি ইনপুট করুন:
ফাইলের নাম: src/main.rs
fn main() { let number = 3; if number < 5 { println!("condition was true"); } else { println!("condition was false"); } }
সমস্ত if এক্সপ্রেশন if কীওয়ার্ড দিয়ে শুরু হয়, তারপরে একটি শর্ত থাকে। এই ক্ষেত্রে, শর্তটি পরীক্ষা করে যে number ভ্যারিয়েবলের মান ৫ এর চেয়ে কম কিনা। শর্তটি true হলে কার্যকর করার জন্য কোড ব্লকটি আমরা শর্তের পরেই কোঁকড়া বন্ধনীর ভিতরে রাখি। if এক্সপ্রেশনের শর্তগুলোর সাথে যুক্ত কোড ব্লকগুলোকে কখনও কখনও arms বলা হয়, ঠিক যেমন অধ্যায় ২-এর "অনুমানের সাথে গোপন সংখ্যার তুলনা" বিভাগে আলোচনা করা match এক্সপ্রেশনের arm-গুলোর মতো।
ঐচ্ছিকভাবে, আমরা একটি 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");
}
}```
প্রোগ্রামটি আবার চালান, এবং আউটপুট দেখুন:
```console
$ 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` না হয়, আমরা একটি এরর পাব। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি চালানোর চেষ্টা করুন:
<span class="filename">ফাইলের নাম: src/main.rs</span>
```rust,ignore,does_not_compile
fn main() {
let number = 3;
if number {
println!("number was three");
}
}
if-এর শর্তটি এবার 3 মান দেয়, এবং রাস্ট একটি এরর দেখায়:
$ 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
এররটি নির্দেশ করে যে রাস্ট একটি bool আশা করেছিল কিন্তু একটি ইন্টিজার পেয়েছে। রুবি এবং জাভাস্ক্রিপ্টের মতো ভাষার বিপরীতে, রাস্ট স্বয়ংক্রিয়ভাবে নন-বুলিয়ান টাইপকে বুলিয়ানে রূপান্তর করার চেষ্টা করবে না। আপনাকে অবশ্যই সুস্পষ্ট হতে হবে এবং if-কে সর্বদা একটি বুলিয়ান শর্ত হিসাবে সরবরাহ করতে হবে। যদি আমরা চাই যে if কোড ব্লকটি কেবল তখনই চলুক যখন একটি সংখ্যা 0-এর সমান না হয়, উদাহরণস্বরূপ, আমরা if এক্সপ্রেশনটিকে নিম্নলিখিতভাবে পরিবর্তন করতে পারি:
ফাইলের নাম: 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 দিয়ে একাধিক শর্ত পরিচালনা করা
আপনি if এবং else-কে একটি else if এক্সপ্রেশনে একত্রিত করে একাধিক শর্ত ব্যবহার করতে পারেন। উদাহরণস্বরূপ:
ফাইলের নাম: 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 টেক্সটটিও দেখতে পাই না। এর কারণ হল রাস্ট কেবল প্রথম true শর্তের জন্য ব্লকটি কার্যকর করে, এবং একবার এটি একটি খুঁজে পেলে, এটি বাকিগুলো আর পরীক্ষাই করে না।
অনেক বেশি else if এক্সপ্রেশন ব্যবহার করলে আপনার কোড অগোছালো হয়ে যেতে পারে, তাই আপনার যদি একাধিক থাকে, তবে আপনি আপনার কোড রিফ্যাক্টর করতে চাইতে পারেন। অধ্যায় ৬ এই ধরনের ক্ষেত্রে match নামে একটি শক্তিশালী রাস্ট ব্রাঞ্চিং কনস্ট্রাক্ট বর্ণনা করে।
একটি let স্টেটমেন্টে if ব্যবহার করা
যেহেতু if একটি এক্সপ্রেশন, তাই আমরা এটিকে একটি let স্টেটমেন্টের ডানদিকে ব্যবহার করে ফলাফলটি একটি ভ্যারিয়েবলে অ্যাসাইন করতে পারি, যেমনটি লিস্টিং ৩-২-এ দেখানো হয়েছে।
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 থেকে ফলাফল হিসাবে আসার সম্ভাবনা থাকা মানগুলোর টাইপ অবশ্যই একই হতে হবে; লিস্টিং ৩-২-এ, if arm এবং else arm উভয়ের ফলাফলই i32 ইন্টিজার ছিল। যদি টাইপগুলো বেমানান হয়, যেমন নিম্নলিখিত উদাহরণে, আমরা একটি এরর পাব:
ফাইলের নাম: src/main.rs
fn main() {
let condition = true;
let number = if condition { 5 } else { "six" };
println!("The value of number is: {number}");
}
যখন আমরা এই কোডটি কম্পাইল করার চেষ্টা করব, আমরা একটি এরর পাব। if এবং else arm-গুলোর মানের টাইপ বেমানান, এবং রাস্ট প্রোগ্রামের ঠিক কোথায় সমস্যাটি খুঁজে পাওয়া যাবে তা নির্দেশ করে:
$ 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 ব্লকের এক্সপ্রেশনটি একটি স্ট্রিং-এ রূপান্তরিত হয়। এটি কাজ করবে না কারণ ভ্যারিয়েবলগুলোর অবশ্যই একটি একক টাইপ থাকতে হবে, এবং রাস্টকে কম্পাইল করার সময় নির্দিষ্টভাবে জানতে হবে number ভ্যারিয়েবলের টাইপ কী। number-এর টাইপ জানা থাকলে কম্পাইলার যাচাই করতে পারে যে আমরা যেখানেই number ব্যবহার করি সেখানে টাইপটি বৈধ। রাস্ট এটি করতে পারত না যদি number-এর টাইপ কেবল রানটাইমে নির্ধারিত হত; কম্পাইলার আরও জটিল হত এবং কোড সম্পর্কে কম গ্যারান্টি দিত যদি তাকে যেকোনো ভ্যারিয়েবলের জন্য একাধিক কাল্পনিক টাইপের হিসাব রাখতে হত।
লুপ দিয়ে পুনরাবৃত্তি (Repetition with Loops)
প্রায়শই একটি কোড ব্লক একাধিকবার চালানো দরকার হয়। এই কাজের জন্য, রাস্ট বিভিন্ন লুপ (loops) সরবরাহ করে, যা লুপ বডির ভিতরের কোড শেষ পর্যন্ত চালাবে এবং তারপরে অবিলম্বে শুরুতে ফিরে যাবে। লুপ নিয়ে পরীক্ষা করার জন্য, চলুন loops নামে একটি নতুন প্রজেক্ট তৈরি করি।
রাস্টের তিন ধরনের লুপ রয়েছে: loop, while, এবং for। চলুন প্রতিটি চেষ্টা করি।
loop দিয়ে কোডের পুনরাবৃত্তি করা
loop কীওয়ার্ড রাস্টকে বলে একটি কোড ব্লক বারবার চালাতে, চিরকালের জন্য অথবা যতক্ষণ না আপনি স্পষ্টভাবে এটিকে থামাতে বলেন।
উদাহরণস্বরূপ, আপনার loops ডিরেক্টরিতে src/main.rs ফাইলটি পরিবর্তন করে এইরকম করুন:
ফাইলের নাম: 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! শব্দটি দেখতেও পারেন বা নাও দেখতে পারেন, এটি নির্ভর করে কোডটি লুপের কোথায় ছিল যখন এটি ইন্টারাপ্ট সিগন্যাল পেয়েছিল।
সৌভাগ্যবশত, রাস্ট কোড ব্যবহার করে একটি লুপ থেকে বেরিয়ে আসার একটি উপায়ও সরবরাহ করে। আপনি লুপের মধ্যে break কীওয়ার্ডটি রাখতে পারেন প্রোগ্রামকে বলতে যে কখন লুপ চালানো বন্ধ করতে হবে। মনে রাখবেন যে আমরা অধ্যায় ২-এর "সঠিক অনুমান করার পরে খেলা শেষ করা" বিভাগে এটি করেছিলাম, যখন ব্যবহারকারী সঠিক সংখ্যা অনুমান করে গেমটি জিতেছিল তখন প্রোগ্রাম থেকে বেরিয়ে আসার জন্য।
আমরা গেসিং গেমে continue ব্যবহার করেছিলাম, যা একটি লুপে প্রোগ্রামকে বলে যে এই পুনরাবৃত্তির বাকি কোড এড়িয়ে গিয়ে পরবর্তী পুনরাবৃত্তিতে যেতে।
লুপ থেকে মান রিটার্ন করা
একটি 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 সর্বদা বর্তমান ফাংশন থেকে বেরিয়ে যায়।
একাধিক লুপের মধ্যে পার্থক্য করতে লুপ লেবেল
যদি আপনার লুপের ভিতরে লুপ থাকে, break এবং continue সেই মুহূর্তে সবচেয়ে ভিতরের লুপে প্রযোজ্য হয়। আপনি ঐচ্ছিকভাবে একটি লুপে একটি লুপ লেবেল (loop label) নির্দিষ্ট করতে পারেন যা আপনি তখন 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 দিয়ে শর্তাধীন লুপ
একটি প্রোগ্রামে প্রায়শই একটি লুপের মধ্যে একটি শর্ত মূল্যায়ন করার প্রয়োজন হয়। যতক্ষণ শর্তটি true থাকে, লুপ চলে। যখন শর্তটি true থাকা বন্ধ হয়ে যায়, প্রোগ্রামটি break কল করে, লুপটি থামিয়ে দেয়। loop, if, else, এবং break-এর সংমিশ্রণ ব্যবহার করে এই ধরনের আচরণ বাস্তবায়ন করা সম্ভব; আপনি চাইলে এখন একটি প্রোগ্রামে এটি চেষ্টা করতে পারেন। তবে, এই প্যাটার্নটি এত সাধারণ যে রাস্টের এটির জন্য একটি অন্তর্নির্মিত ভাষা কনস্ট্রাক্ট রয়েছে, যাকে while লুপ বলা হয়। লিস্টিং ৩-৩-এ, আমরা while ব্যবহার করি প্রোগ্রামটিকে তিনবার লুপ করতে, প্রতিবার গণনা করে, এবং তারপরে, লুপের পরে, একটি বার্তা প্রিন্ট করে এবং প্রস্থান করে।
fn main() { let mut number = 3; while number != 0 { println!("{number}!"); number -= 1; } println!("LIFTOFF!!!"); }
এই কনস্ট্রাক্টটি অনেক নেস্টিং দূর করে যা আপনি যদি loop, if, else, এবং break ব্যবহার করতেন তবে প্রয়োজন হত, এবং এটি আরও স্পষ্ট। যতক্ষণ একটি শর্ত true থাকে, কোড চলে; অন্যথায়, এটি লুপ থেকে বেরিয়ে যায়।
for দিয়ে একটি কালেকশনের মাধ্যমে লুপিং করা
আপনি একটি কালেকশনের উপাদানগুলোর উপর লুপ করার জন্য while কনস্ট্রাক্ট ব্যবহার করতে পারেন, যেমন একটি অ্যারে। উদাহরণস্বরূপ, লিস্টিং ৩-৪-এর লুপটি 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 লুপ লিস্টিং ৩-৫-এর কোডের মতো দেখায়।
fn main() { let a = [10, 20, 30, 40, 50]; for element in a { println!("the value is: {element}"); } }
যখন আমরা এই কোডটি চালাব, আমরা লিস্টিং ৩-৪-এর মতো একই আউটপুট দেখতে পাব। আরও গুরুত্বপূর্ণভাবে, আমরা এখন কোডের নিরাপত্তা বাড়িয়েছি এবং অ্যারের শেষের বাইরে যাওয়া বা যথেষ্ট দূরে না গিয়ে কিছু আইটেম বাদ দেওয়ার ফলে হতে পারে এমন বাগের সম্ভাবনা দূর করেছি। for লুপ থেকে তৈরি মেশিন কোড আরও কার্যকর হতে পারে, কারণ প্রতিটি পুনরাবৃত্তিতে ইনডেক্সকে অ্যারের দৈর্ঘ্যের সাথে তুলনা করার প্রয়োজন হয় না।
for লুপ ব্যবহার করলে, আপনি যদি অ্যারের মানের সংখ্যা পরিবর্তন করেন তবে অন্য কোনো কোড পরিবর্তন করার কথা মনে রাখার প্রয়োজন হবে না, যেমনটি লিস্টিং ৩-৪-এ ব্যবহৃত পদ্ধতিতে করতে হত।
for লুপের নিরাপত্তা এবং সংক্ষিপ্ততা তাদের রাস্ট-এ সবচেয়ে বেশি ব্যবহৃত লুপ কনস্ট্রাক্ট করে তুলেছে। এমনকি যে পরিস্থিতিতে আপনি একটি নির্দিষ্ট সংখ্যক বার কিছু কোড চালাতে চান, যেমন লিস্টিং ৩-৩-এ while লুপ ব্যবহার করা কাউন্টডাউন উদাহরণে, বেশিরভাগ রাস্টেশিয়ান একটি for লুপ ব্যবহার করবে। এটি করার উপায় হল একটি Range ব্যবহার করা, যা স্ট্যান্ডার্ড লাইব্রেরি দ্বারা সরবরাহ করা হয়, যা একটি সংখ্যা থেকে শুরু করে এবং অন্য একটি সংখ্যার আগে শেষ হওয়া পর্যন্ত ক্রমানুসারে সমস্ত সংখ্যা তৈরি করে।
এখানে for লুপ এবং আরেকটি মেথড যা আমরা এখনও আলোচনা করিনি, rev (রেঞ্জটি উল্টো করার জন্য) ব্যবহার করে কাউন্টডাউনটি কেমন দেখাবে:
ফাইলের নাম: src/main.rs
fn main() { for number in (1..4).rev() { println!("{number}!"); } println!("LIFTOFF!!!"); }
এই কোডটি একটু সুন্দর, তাই না?
সারাংশ
আপনি পেরেছেন! এটি একটি বড় অধ্যায় ছিল: আপনি ভ্যারিয়েবল, স্কেলার এবং কম্পাউন্ড ডেটা টাইপ, ফাংশন, কমেন্ট, if এক্সপ্রেশন এবং লুপ সম্পর্কে শিখেছেন! এই অধ্যায়ে আলোচিত ধারণাগুলো অনুশীলন করার জন্য, নিম্নলিখিত কাজগুলো করার জন্য প্রোগ্রাম তৈরি করার চেষ্টা করুন:
- ফারেনহাইট এবং সেলসিয়াসের মধ্যে তাপমাত্রা রূপান্তর করুন।
- n-তম ফিবোনাচি সংখ্যা তৈরি করুন।
- ক্রিসমাস ক্যারোল "The Twelve Days of Christmas"-এর লিরিক্স প্রিন্ট করুন, গানের পুনরাবৃত্তির সুবিধা নিয়ে।
যখন আপনি এগিয়ে যাওয়ার জন্য প্রস্তুত হবেন, আমরা রাস্টের এমন একটি ধারণা নিয়ে কথা বলব যা অন্যান্য প্রোগ্রামিং ভাষায় সাধারণত বিদ্যমান নেই: ওনারশিপ (ownership)।