ক্লোজার হচ্ছে স্পেশাল ফাংশন, যেটা ভ্যারিয়েবল বা কনস্ট্যান্টের মত ব্যবহার করা যায়, এমনকি অন্য ফাংশনের প্যারামিটার হিসেবেও পাস করা যায়। অন্যান্য প্রোগ্রামিং এ যা ল্যাম্বডা, অ্যাননিমাস ফাংশন এবং অবজেক্টিভ সিতে ব্লক নামে পরিচিত।
ক্লোজারের সিনট্যাক্সঃ ক্লোজারের সাধারণ ফরম হচ্ছে নিচের মতঃ
{ (parameters) -> ReturnType in
// Closure body
}
আমরা যে কোন ফাংশনকেই ক্লোজার হিসেবে লিখতে পারি। নিচের ফাংশনটি দেখিঃ
func add(a: Int, b: Int) -> Int {
return a + b
}
যেটার ক্লোজার রূপ হবে এমনঃ
let add = { (a: Int, b: Int) -> Int in
return a + b
}
আমরা ফাংশনের মত ক্লোজার ব্যবহার করতে পারিঃ
let add = { (a: Int, b: Int) -> Int in
return a + b
}
print(add(2,2))
ক্লোজারের ইনপুট টাইপঃ
ভ্যারিয়েবল বা কনস্ট্যান্টের মত ক্লোজার ইনপুটের টাইপ অনুমান করে নিতে পারে। তা উপরের কোড থেকে প্যারামিটার টাইপ Int
অংশ বাদ দিতে পারিঃ
let add = { (a, b) -> Int in
return a + b
}
print(add(2,2))
ফাংশনের প্যারামিটার হিসেবে ক্লোজারঃ
ফাংশনের প্যারামিটার হিসেবে আমরা ক্লোজার ব্যবহার করতে পারি। যেমনঃ
let add = { (a, b) -> Int in
return a + b
}
func getSquare( num: Int) -> Int {
return num*num
}
// passing add closure to getSquare function
print(getSquare(num: add(2,3)))
সুইফটের স্ট্যান্ডার্ড লাইব্রেরী মেথডের সাথে ক্লোজার
সুইফটের স্ট্যান্ডার্ড লাইব্রেরী মেথড sorted
, map
and filter
ইত্যাদির সাথে ক্লোজার ব্যবহার করা যায়। এই মেথড গুলো প্যারামিটার হিসেবে ক্লোজার গ্রহণ করে। যেমন sorted মেথড যদি দেখি, আমরা যে কোন অ্যারে সাজিয়ে নিতে পারব sorted() মেথড ব্যবহার করে।
let numbers = [5, 2, 6, 8, 1, 7]
let sortedNumbers = numbers.sorted()
// Output: [[1, 2, 5, 6, 7, 8]]
print(sortedNumbers)
কিভাবে এই অ্যারের ইলিমেন্ট গুলো সর্ট করবে, তা বলে দিতে পারি ক্লোজারের মাধ্যমেঃ
let numbers = [5, 2, 6, 8, 1, 7]
let sortedNumbers = numbers.sorted(by: { (a: Int, b: Int) -> Bool in
return a > b
})
// Output: [8, 7, 6, 5, 2, 1]
print(sortedNumbers)
উপরে ক্লোজারের মাধ্যমে আমরা বলে দিয়েছি অ্যারের ইলিমেন্ট গুলোকে বড় থেকে ছোট আকারে সাজাতে। sorted() মেথডের ভেতর যে কোড লিখেছি, তা হচ্ছে ক্লোজার। নিচের ফরমের মতঃ
{ (parameters) -> ReturnType in
// Closure body
}
উপরের ক্লোজারে ইনপুট হিসেবে দুইটা আইটেম গ্রহণ করে, এরপর যে আইটেম বড়, তা রিটার্ণ করে। আমরা জেনেছি ক্লোজার টাইপ অনুমান করে নিতে পারে। তাই উপরের ক্লোজার থেকে টাইপ বাদ দিতে পারিঃ
let sortedNumbers = numbers.sorted(by: { a , b in
return a > b
})
ইমপ্লিসিট রিটার্ণ
যে ক্লোজারে একটাই মাত্র এক্সপ্রেশন লেখা হয়, সেখানে সাধারণত retrun কিওয়ার্ড ব্যবহার না করলেও হয়। এর ফলে ক্লোজার আরো সুন্দর করে এক লাইনেই লেখা যায়। যেমন উপরের কোড আমরা এভাবে লিখতে পারিঃ
let sortedNumbers = numbers.sorted(by: { a , b in a > b })
শর্টহ্যান্ড আর্গুমেন্ট
ইনলাইন ক্লোজারের জন্য সুইফট শর্টহ্যান্ড আর্গুমেন্ট যেমন $0, $1, $2 ইত্যাদি ব্যবহার করার সুবিধা দেয়। এখানে $0 মানে আর্গুমেন্টের প্রথম আইটেম, $1 মানে আর্গুমেন্টের দ্বিতীয় আইটেম ইত্যাদি। a, b এর পরিবর্তে আমরা এই শর্টহ্যান্ড আর্গুমেন্ট ব্যবহার করতে পারি। আর শর্টহ্যান্ড আর্গুমেন্ট ব্যবহার করলে আলাদা করে আর in
ব্যবহার করা লাগে না। তাই উপরের কোড এভাবে লেখা যাবেঃ
let sortedNumbers = numbers.sorted(by: { $0 > $1 })
ট্রেইলিং ক্লোজার
কোন ফাংশনের আর্গুমেন্ট হিসেবে যদি আমরা কোন ক্লোজার পাস করি এবং ঐটা ঐ ফাংশনের সর্বশেষ আর্গুমেন্ট হয়, তাহলে আমরা ফাংশনের প্যারেন্থেসিসের পর ক্লোজার লিখতে পারি। সাধারণত ক্লোজার বডি যদি বড় হয়, থালে এভাবে লেখা হয়। সহজে বুঝার জন্য আমরা নিচের উদাহরণটি দেখিঃ
numbers.sorted(by: { $0 > $1 })
// trailing closure of this code will be
numbers.sorted() { $0 > $1 }
ম্যাপ ম্যাথডে ক্লোজার ব্যবহার
উপড়ে আমরা দেখেছি সর্টিং স্ট্যান্ডার্ড লাইব্রেরীর সাথে ক্লোজারের ব্যবহার। নিচে ম্যাপ মেথডে ক্লোজার কিভাবে ব্যবহার করতে পারি, তার একটা উদাহরণ দেওয়া হলোঃ
let numbers = [5, 2, 6, 8, 1, 7]
let doubledNumbers = numbers.map {$0 * 2}
// Output: [10, 4, 12, 16, 2, 14]
print(doubledNumbers)
ফিল্টার ম্যাথডে ক্লোজার
কোন অ্যারে ফিল্টার করার জন্য আমরা ক্লোজার ব্যবহার করতে পারি। যেমনঃ
let numbers = [5, 2, 6, 8, 1, 7]
let evenNumbers = numbers.filter { $0 % 2 == 0 }
// Output: [2, 6, 8]
print(evenNumbers)