কোনো একটি Swift ফাংশন সিগনেচার থেকে সব নাম ও লেবেল সরিয়ে দিলে কেবল ফাংশনটির টাইপ পড়ে থাকবে।
func shoppingList(item: String, quantity: Int) -> String {
"You need to buy \(quantity) \(item)."
}
// shoppingList: (String, Int) -> String
func repeater(_ phrase: String, times: Int) -> String {
var result = ""
for _ in 1...times {
result += phrase
}
return result
}
// repeater: (String, Int) -> String
func printString(line: String) {
print(line)
}
// printString: (String) -> ()
লক্ষ্য করুন, প্রথম দুটি ফাংশনের টাইপ একই, (String, Int) -> String, যদিও দুটি সিগনেচার আলাদা এবং দুটি ফাংশন খুব ভিন্নভাবে কাজ করে। দুটিই ইনপুট হিসেবে একটি String ও একটি Int নেয় এবং একটি String রিটার্ন করে। আর তৃতীয় ফাংশনের টাইপ দেখে বোঝা যায়, ফাংশন বডি আপাতদৃষ্টিতে কিছু রিটার্ন করে না হলেও, আসলে এটি অন্তর্নিহিতভাবে () রিটার্ন করে, যা Void টাইপের একমাত্র মান।
এই ফাংশন টাইপগুলো Swift-এ অন্য যেকোনো টাইপের মতোই ব্যবহার করা যায়; উদাহরণস্বরূপ, ভ্যারিয়েবল বা কনস্ট্যান্ট ঘোষণায় এগুলো ব্যবহার করা যায়। আর যেহেতু Swift-এ ফাংশন একটি মান, তাই আগে থেকে থাকা ফাংশনগুলো এই কনস্ট্যান্ট/ভ্যারিয়েবলগুলোতে অ্যাসাইন করা যায়:
var stringAndIntToString: (String, Int) -> String
stringAndIntToString = shoppingList
stringAndIntToString("carrots", 3)
// => "You need to buy 3 carrots."
অন্য ভ্যারিয়েবল/কনস্ট্যান্টের মতোই, এতে আপনি যে মানটি অ্যাসাইন করবেন সেটি অবশ্যই সঠিক টাইপের হতে হবে:
stringAndIntToString = printShoppingList
// Error: Cannot assign value of type '(String) -> ()' to type '(String, Int) -> String'
যেহেতু অন্য যেকোনো টাইপ যেখানে ব্যবহার করা যায়, ফাংশন টাইপও সেখানে ব্যবহার করা যায়, তাই এগুলো প্যারামিটার টাইপ হিসেবেও ব্যবহার করা যায়, অন্য ফাংশনে পাস করা যায় এবং সেই ফাংশনের ভেতর থেকে কল করা যায়।
func apply3(to str: String, function f: (String, Int) -> String) -> String {
f(str,3)
}
// apply3: ([String], (String, Int) -> String) -> [String]
apply3(to: "eggs", function: shoppingList)
// => "You need to buy 3 eggs."
apply3(to: "eggs", function: repeater)
// => "eggseggseggs"
একইভাবে, ফাংশনের রিটার্ন টাইপ হিসেবে ফাংশন টাইপ ব্যবহার করা যায়। অন্যভাবে বললে, এমন ফাংশন লেখা যায় যেগুলো অন্য ফাংশন তৈরি করে এবং রিটার্ন করে। এসব ফাংশন তৈরি করার সময়, যে ফাংশনটি রিটার্ন করা হয় সেটি ফাংশনে পাস করা অন্য প্যারামিটারগুলো বা প্যারেন্ট ফাংশনের ভেতরে তৈরি করা লোকাল ভ্যারিয়েবলগুলো ব্যবহার করতে পারে।
func makeAdder(base: Int) -> (Int) -> Int {
func adder(_ i: Int) -> Int {
base + i
}
return adder
}
// makeAdder: (Int) -> (Int) -> Int
let add10 = makeAdder(base: 10)
// add10: (Int) -> Int
let subtract20 = makeAdder(base: -20)
// subtract10: (Int) -> Int
add10(5)
// => 15
subtract20(5)
// => -15
হ্যালো, এজেন্ট ডাবল-নাল0111।
আপনার মিশন, যদি আপনি এটি গ্রহণ করার সিদ্ধান্ত নেন, হলো UMBRA (United Minions Being Really Awful) সদর দপ্তরে অনুপ্রবেশ করে তাদের সর্বশেষ সত্যিই ভয়াবহ পরিকল্পনার নকশা উদ্ধার করতে সাহায্য করার জন্য দুটি টুল লেখা। এই মিশন সম্পন্ন করতে আপনার দুটি টুল লাগবে।
গোপন নকশা হাতে এলে আপনাকে সেটি এমনভাবে সুরক্ষিত করতে হবে যাতে কেবল যারা পাসওয়ার্ড জানে তারাই সেগুলো উদ্ধার করতে পারে।
এটি করতে হলে আপনাকে protectSecret(_ secret: String, withPassword password: String) -> (String) -> String ফাংশনটি ইমপ্লিমেন্ট করতে হবে।
এই ফাংশনটি আরেকটি ফাংশন রিটার্ন করবে, যা ইনপুট হিসেবে সম্ভাব্য পাসওয়ার্ড স্ট্রিং নেয়।
লেখা পাসওয়ার্ডটি সঠিক হলে নতুন ফাংশনটি লুকানো নকশাটি রিটার্ন করে, কিন্তু পাসওয়ার্ডটি ভুল হলে ফাংশনটি "Sorry. No hidden secrets here." রিটার্ন করে।
let secretFunction = protectSecret("Steal the world's supply of french fries!", withPassword: "5up3r53cr37")
secretFunction("Open sesame")
// Returns "Sorry. No hidden secrets here."
secretFunction("5up3r53cr37")
// Returns "Steal the world's supply of french fries!"
আমরা জেনেছি, UMBRA তাদের সব সেফের কম্বিনেশন ঠিক করে সেটি যে ঘরে রাখা আছে সেই ঘরের নম্বরের ভিত্তিতে। ঘরের নম্বরে বারবার একটি বিশেষ ফাংশন প্রয়োগ করে সেফের কম্বিনেশন তৈরি করা হয়। তাই কম্বিনেশনের প্রথম সংখ্যাটি আসে ঘরের নম্বরে ফাংশনটি প্রয়োগ করে, দ্বিতীয়টি আসে প্রথম সংখ্যাটিতে ফাংশনটি প্রয়োগ করে, আর তৃতীয়টি আসে দ্বিতীয় সংখ্যাটিতে ফাংশনটি প্রয়োগ করে।
তবে UMBRA নিয়মিতই কম্বিনেশন তৈরিতে ব্যবহৃত ফাংশন বদলে দেয়, তাই কম্বিনেশন তৈরি করতে আপনার টুলকে ঘরের নম্বর এবং উপযুক্ত ফাংশন দুটোই নিতে হবে।
আপনার প্রয়োজনীয় কম্বিনেশনটি তৈরি করতে generateCombination(forRoom room: Int, usingFunction f: (Int) -> Int) -> (Int, Int, Int) ফাংশনটি ইমপ্লিমেন্ট করুন।
func makeCombo(_ x: Int) -> Int {
(x * 13) % 256
}
generateCombination(forRoom: 227, usingFunction: makeCombo)
// Returns (135, 219, 31)
Exercism-এ সাইন আপ করুন, Swift ট্র্যাকের 35টি কনসেপ্ট116টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।