ফাংশনের টাইপ অ্যানোটেশনের পরে প্যারামিটার লিস্টে প্যারামিটারে একটি মান অ্যাসাইন করে ফাংশনের যেকোনো প্যারামিটারের জন্য ডিফল্ট প্যারামিটার মান দেওয়া যায়। যখন একটি ডিফল্ট প্যারামিটার মান নির্দিষ্ট করা হয়, তখন ফাংশনটি কল করার সময় কলকারী ওই প্যারামিটারটি বাদ দিতে পারেন এবং তার বদলে ডিফল্ট মানটি ব্যবহৃত হয়।
func greeting(name: String = "guest", duration: Int = 2) -> String {
"Welcome, \(name). Enjoy your \(duration) night stay."
}
greeting(name: "Bobo", duration: 7)
// Returns "Welcome, Bobo. Enjoy your 7 night stay."
greeting(duration: 3)
// Returns "Welcome, guest. Enjoy your 3 night stay."
greeting(name: "Wynona")
// Returns "Welcome, Wynona. Enjoy your 2 night stay."
greeting()
// Returns "Welcome, guest. Enjoy your 2 night stay."
ভ্যারিয়াডিক প্যারামিটার একটি ফাংশনকে একটি নির্দিষ্ট টাইপের শূন্য বা তার বেশি মান একটি একক প্যারামিটারের জন্য গ্রহণ করার সুযোগ দেয়।
প্যারামিটারের টাইপ অ্যানোটেশনের শেষে তিনটি ডট (...) যোগ করে আপনি একটি ভ্যারিয়াডিক প্যারামিটার ডিফাইন করেন।
ফাংশন বডির ভেতরে Swift এই মানগুলোকে নির্দিষ্ট টাইপের একটি অ্যারে হিসেবে ব্যবহারের জন্য উপলব্ধ করে:
import Foundation
func geometricMean(_ numbers: Double...) -> Double {
var total = 1.0
for number in numbers {
total *= number
}
return pow(total, 1.0 / Double(numbers.count))
}
let result = geometricMean(1, 2, 3, 4, 5)
// result is 2.605171084697352
কোনো ফাংশনে ভ্যারিয়াডিক প্যারামিটারের পরে অতিরিক্ত প্যারামিটার থাকলে, ভ্যারিয়াডিক প্যারামিটারটির পরে আসা প্রথম প্যারামিটারের একটি স্পষ্ট আর্গুমেন্ট লেবেল থাকতেই হবে, যাতে Swift বুঝতে পারে ভ্যারিয়াডিক আর্গুমেন্ট লিস্টটি কোথায় শেষ হচ্ছে।
ফাংশনের বডির ভেতরে প্যারামিটারগুলোকে কনস্ট্যান্ট হিসেবে ধরা হয়, ভ্যারিয়েবল হিসেবে নয়; কোনো প্যারামিটারের মান পরিবর্তন করার চেষ্টা করলে একটি কম্পাইল-টাইম এরর হবে। কোনো ফাংশন যদি প্যারামিটারের মান পরিবর্তন করতে চায়, তাহলে এই পরিবর্তনযোগ্যতাটি স্পষ্ট করতে তাকে একটি ইন-আউট প্যারামিটার ব্যবহার করতে হবে।
ইন-আউট প্যারামিটার ব্যবহার করতে একজন প্রোগ্রামারকে তিনটি বিষয়ে নিশ্চিত হতে হবে:
: এবং টাইপ নামের মাঝখানে inout কিওয়ার্ড লিখে ইন-আউট প্যারামিটারগুলোকে স্পষ্টভাবে চিহ্নিত করতে হবে।& থাকতে হবে, যা এটিকে পরিবর্তনযোগ্য হিসেবে স্পষ্টভাবে চিহ্নিত করে।এটি করা হলে ফাংশনটি ইন-আউট প্যারামিটারের একটি অভ্যন্তরীণ কপি তৈরি করে, ফাংশনের বডিতে নির্দেশ অনুযায়ী তা পরিবর্তন করে, এবং ফাংশন রিটার্ন করার সময় পরিবর্তিত মানটি আবার সেই ভ্যারিয়েবলে কপি করে দেয়, যেটি পাঠানো হয়েছিল।
func updateVersion(_ record: inout (version: Int, title: String)) {
record.version += 1
}
var dbRecord = (version: 2, title: "Exercism")
updateVersion(&dbRecord)
// dbRecord is now (3, "Exercism")
ইন-আউট প্যারামিটার নিয়ে আরও কয়েকটি অতিরিক্ত নিয়ম সম্পর্কে সচেতন থাকা উচিত।
1 ইন-আউট প্যারামিটারযুক্ত কোনো ফাংশনের ভেতরে, যে ভ্যারিয়েবলটি ইন-আউট প্যারামিটার হিসেবে পাঠানো হয়েছিল, সেটি রেফারেন্স করার অনুমতি নেই।
2. একই ফাংশনে একই ভ্যারিয়েবল একাধিক ইন-আউট প্যারামিটার হিসেবে পাঠানো যাবে না।
উদাহরণস্বরূপ, `inoutFunc(&mutVar, &mutVar)` একটি কম্পাইলার এরর তৈরি করে।
Swift-এ আপনি অন্য ফাংশনের ভেতরে ফাংশন ডিফাইন করতে পারেন। এগুলোকে নেস্টেড ফাংশন বলা হয়।
নেস্টেড ফাংশন সাধারণত প্রাইভেট হেল্পার হিসেবে ব্যবহৃত হয়, যেগুলো বাইরের স্কোপ নষ্ট না করে নিজেকে ঘিরে থাকা ফাংশনের জন্য নির্দিষ্ট কিছু কাজ করে:
func makeNumber(_ number: Int) -> Int {
func double(_ x: Int) -> Int {
x * 2
}
func increment(_ x: Int) -> Int {
x + 1
}
return number.isMultiple(of: 2) ? increment(double(number)) : double(number)
}
print(makeNumber(3)) // Prints 6
print(makeNumber(4)) // Prints 9
নেস্টেড ফাংশনগুলো সাধারণ ফাংশনের মতোই আচরণ করে, কিন্তু এগুলোর দৃশ্যমানতা ঘিরে থাকা ফাংশনের বডির মধ্যেই সীমাবদ্ধ।
এই অনুশীলনীতে আপনি আরও কিছু কোড লিখবেন, যা আপনার প্রিয় রান্নার বই থেকে শেখা দুর্দান্ত লাসানিয়া রান্না করতে সাহায্য করবে।
আপনার সামনে পাঁচটি কাজ, যার সবকটিই লাসানিয়া রান্নায় ব্যয় হওয়া সময়ের সাথে সম্পর্কিত।
আপনি একটি উন্নত remainingMinutesInOven ফাংশন লিখতে চান, যা প্যারামিটার হিসেবে লাসানিয়া কত মিনিট ধরে ওভেনে আছে সেই সংখ্যাটি নেয় এবং আগের কাজে নির্ধারিত ওভেনে প্রত্যাশিত সময়ের ভিত্তিতে রিটার্ন করে, লাসানিয়াকে আর কত মিনিট ওভেনে থাকতে হবে।
আগে আপনি remainingMinutesInOven ফাংশনের বাইরে থেকে আসা একটি কনস্ট্যান্ট মান, expectedMinutesInOven-এর উপর নির্ভর করেছিলেন।
এটা আপনার কাছে একটু বেশি জটিলও লাগছিল, আবার যথেষ্ট নমনীয়ও ছিল না, কারণ এতে ওভেনে প্রত্যাশিত সময় বদলানোর সুযোগ ছিল না।
সবকিছু গুছিয়ে নিতে remainingMinutesInOven ফাংশনটি ডিফাইন করুন, যা প্যারামিটার হিসেবে লাসানিয়া কত মিনিট ধরে ওভেনে আছে সেই সংখ্যাটি নেয়, আর সেই সাথে একটি expectedMinutesInOven প্যারামিটারও নেয় যার ডিফল্ট মান ৪০।
আপনার ফাংশনটি আগের কাজে নির্ধারিত ওভেনে প্রত্যাশিত সময়ের ভিত্তিতে রিটার্ন করবে, লাসানিয়াকে আর কত মিনিট ওভেনে থাকতে হবে।
remainingMinutesInOven(elapsedMinutes: 30)
// Returns 10
remainingMinutesInOven(elapsedMinutes: 30, expectedMinutesInOven: 75)
// Returns 45
আপনি আগে একটি preparationTimeInMinutes ফাংশন লিখেছিলেন, যা প্যারামিটার হিসেবে আপনার লাসানিয়ায় যোগ করা স্তরের সংখ্যা নেয় এবং রিটার্ন করে লাসানিয়া প্রস্তুত করতে আপনি কত মিনিট ব্যয় করেছেন, এই ধরে নিয়ে যে প্রতিটি স্তর প্রস্তুত করতে আপনার ২ মিনিট লাগে।
তবে এই ফাংশনটি নিয়ে আপনি বিশেষ খুশি নন, কারণ এটি কল করার আগে আপনাকে নিজেই আপনার লাসানিয়ার স্তরগুলো গুনতে হয়, আর এসবের জন্য কার সময় আছে?
নিজের কাজ সহজ করতে একটি ফাংশন লিখুন, preparationTimeInMinutes, যা একটি ভ্যারিয়াডিক String প্যারামিটার, layers নেয়, যেখানে আপনি আপনার লাসানিয়ার বিভিন্ন স্তরের তালিকা দেন।
এরপর ফাংশনটি আপনার লাসানিয়ার স্তরের সংখ্যা গুনবে এবং প্রয়োজনীয় প্রস্তুতির সময় রিটার্ন করবে।
preparationTimeInMinutes(layers: "sauce", "noodles")
// Returns 4
preparationTimeInMinutes(layers: "sauce", "noodles", "sauce", "meat", "mozzarella", "noodles", "sauce", "eggplant", "béchamel", "noodles", "sauce", "mozzarella")
// Returns 24
লাসানিয়া সাজানো শুরু করার আগে আপনি নিশ্চিত হতে চান যে আপনার স্বপ্নের লাসানিয়া বানানোর জন্য যথেষ্ট sauce আর noodles হাতে আছে। আপনার লাসানিয়ার প্রতিটি noodle স্তরের জন্য ৩টি noodles লাগবে। আর আপনার লাসানিয়ার প্রতিটি sauce স্তরের জন্য ০.২ লিটার sauce লাগবে।
quantities ফাংশনটি ডিফাইন করুন, যা একটি ভ্যারিয়াডিক String প্যারামিটার, layers নেয়, যেখানে আপনি আপনার লাসানিয়ার বিভিন্ন স্তরের তালিকা দেন।
এরপর ফাংশনটি আপনার খাবার তৈরি করতে কতটুকু noodles ও sauce লাগবে তা নির্ধারণ করবে। ফলাফলটি (noodles: Int, sauce: Double) টাইপের একটি টাপলে রিটার্ন করতে হবে।
quantities(layers: "sauce", "noodles", "sauce", "meat", "mozzarella", "noodles", "sauce", "eggplant", "béchamel", "noodles", "sauce", "mozzarella")
// Returns (noodles: 9, sauce: 0.8)
quantities(layers: "sauce", "noodles", "sauce", "noodles", "meat", "noodles", "mozzarella")
// Returns (noodles: 9, sauce: 0.4)
দুর্ভাগ্যবশত, আপনার হাতে থাকা sauce-এর আয়তন লিটারের বদলে ফ্লুইড আউন্সে লেখা আছে।
হাতে যথেষ্ট sauce আছে কি না তা বুঝতে সাহায্য করার জন্য একটি ফাংশন লিখুন, toOz, যা একটি ইন-আউট টাপল প্যারামিটার, (noodles: Int, sauce: Double) নেয় এবং sauce-এর পরিমাণ ফ্লুইড আউন্সে রূপান্তর করে।
মনে রাখবেন, প্রতি লিটারে ৩৩.৮১৪ ফ্লুইড আউন্স হয়।
var amount = (noodles: 9, sauce: 0.8)
toOz(&amount)
amount
// Returns (noodles: 9, sauce: 27.0512)
সবশেষে, আপনার লাসানিয়ার সাথে কোন ধরনের ওয়াইন পরিবেশন করবেন তা আপনি জানতে চান।
আপনি শুনেছেন, লাসানিয়ায় meat ও sauce-এর চেয়ে mozzarella, ricotta আর béchamel বেশি থাকলে সাদা ওয়াইন পরিবেশন করা উচিত, নাহলে লাল ওয়াইন।
একটি ফাংশন redWine লিখুন, যা একটি ভ্যারিয়াডিক String প্যারামিটার, layers নেয়, যেখানে আপনি আপনার লাসানিয়ার বিভিন্ন স্তরের তালিকা দেন।
ফাংশনটি পাঁচটি নেস্টেড ফাংশন ব্যবহার করে লাসানিয়ায় mozzarella, ricotta, béchamel, sauce ও meat-এর স্তর সংখ্যা নির্ধারণ করবে, এবং স্তরসংখ্যা তুলনা করে ঠিক করবে লাল ওয়াইন পরিবেশন করা উচিত কি না, উচিত হলে true এবং না হলে false রিটার্ন করবে।
redWine(layers: "sauce", "noodles", "sauce", "meat", "mozzarella", "noodles", "sauce", "eggplant", "béchamel", "noodles", "sauce", "mozzarella")
// Returns true
redWine(layers: "sauce", "noodles", "béchamel", "meat", "mozzarella", "noodles", "ricotta", "eggplant", "béchamel", "noodles", "sauce", "mozzarella")
// Returns false
Exercism-এ সাইন আপ করুন, Swift ট্র্যাকের 35টি কনসেপ্ট116টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।