Swift: Overloading ~=

Published by SNNAFI on

আমরা swift এ বিভিন্ন কাজে প্যাটার্ন ম্যাচিং ব্যবহার করি। আমার যখন কোন দুইটা ভ্যালু তুলনা করি তখন কম্পাইলার == ব্যবহার করে উভয় দিক তুলনা করে।কিন্তু অনেক সময় ভ্যালু দুইটা একই টাইপ না হয়ে ভিন্ন টাইপ হতে পারে। যেমনঃ

let range = 1...30
let a = 14

এখানে যদি আমরা তুলনা করতে যাই প্যাটার্ন ম্যাচিং এর সাহায্যে, যেমন,

if case 1...30 = a{
    print("In Range") // true
}

এখানে কম্পাইলার ~= অপারেটর ব্যবহার করে চেক করছে যে, a কি 1…30 মধ্যে আছে কিনা।থাকলে true রিটার্ন করছে তা থাকলে false । আমরা চাইলে এটা সরাসরি এভাবে লিখতে পারি।

let inRange = (1...10 ~= 4)  // true

কিন্তু আমরা যদি [String] সাথে একটা String তুলনা করতে যাই তাহলে কি হবে ?

let names = ["Karim","Rahim","Jalal","Kamal"]

let name = "Jaif" // Expression pattern of type '[String]' cannot match values of type 'String'
if case names = name{
    print("In There")
}

ইরর আসছে।এখন আমাদের ~= অপারেটরকে overload করতে হবে যাতে সেটা String এর ক্ষেত্রেও কাজ করে। না হলে আমাদের তথাগত উপায়ে করতে হবে চেক করার জন্য। যেমনঃ

for i in names where i == name{
     print("In There") // In There
}

for case name in names{
    print("In There") // In There
}

let isContain = names.contains(name) // true

এখন ~= অপারেটরের এর সাহায্যে বের করতে হলে আমাদের নিচের কোডটি লিখে ফেলতে হবে যাতে কম্পাইলার বুঝতে পারে এবং String এর ক্ষেত্রেও কাজ করে।

func ~=(pattern: [String], lookUp: String) -> Bool{
    for i in pattern where i == lookUp {
        return true
    }
    return false
}

এখন যদি আমরা পুনরায় আগের কোডটি লিখি ফেলি তাহলে আমরা দেখব সেটা কাজ করছে।

if case names = name{
    print("In There") // In There
}

isContain = (names ~= name) // true

এখন আমরা খুব সহজেই চেক করতে পারব প্যাটার্ন ম্যাচিং এর সাহায্যে।কিন্তু, একটা সমস্যা রয়ে গেলো। আমরা যদি এখন String ভিন্ন অন্য কোন কিছু যেমন [Int] এর সাথে Int করতে যাই তাহলে আবার ইরর আসবে।আমাদের ~= অপারেটরকে আবার overload করতে হবে Int এর সাথে কাজ করার জন্য ? তাহলে এখন আমরা কি করবো ? আমরা কি আবার Int এর জন্য override করবো ? ধরা যাক, পরবর্তীতে আবার Double এর জন্যও লাগল ? কিম্বা আমাদের কোন কাস্টম টাইপর জন্য? আমরা কি বার বার একেক টাইপের জন্য overload করবো?

না ! আমরা প্রোগ্রামার, আমরা কেন এত কষ্ট করবো? আমরা জেনেরিক টাইপ overload করবো! তাহলেই আমাদের যেকোনো টাইপর জন্য কাজ করবে ! কিন্তু ? আচ্ছা আগে কোড টা লিখে ফেলি!

func ~=<T: Equatable>(pattern: [T], lookUp: T) -> Bool{
    for i in pattern where i == lookUp {
        return true
    }
    return false
}

এখানে আমরা Equatable protocol কনফর্ম করেছি।কারণ কি? আমরা যদি ভালো ভাবে দেখি আমরা মূলত == সাহায্যে লুপিং করে চেক করছি।এখন যদি আমাদের টাইপ == দ্বারা চেক না করা যায় তাহলে ? আমাদের overload কাজ করবে না। ইরর আসবে। সেজন্য আমাদের নিশ্চিত হতে হবে যে আমাদের টাইপ == দ্বারা চেক করা সম্ভব। Int, String, Double, UInt32 ইত্যাদির ক্ষেত্রে Equatable বিল্ড ইন করা আছে। ফলে আমাদের আর মাথা ঘামাতে হবে না। কিন্তু যদি আমরা কোন কাস্টম টাইপ ব্যবহার করি ? তাহলে ?

আমাদের ঐ টাইপ কে Equatable protocol কে কনফর্ম করাতে হবে। যেমনঃ

struct Person: Equatable{
    let name: String
    let age: Int
    init(name: String,age: Int) {
        self.name = name
        self.age = age
    }
}

আমরা যদি Equatable protocol কে কনফর্ম না করি এবং নিচের কোড লিখি তাহলে,

let isPersonHere =  (persons ~= person) // Binary operator '~=' cannot be applied to operands of type '[Person]' and 'Person'

এই জন্য আমাদের আগে Equatable protocol কে কনফর্ম করতে হবে। যদি এখন আমরা পুনরায় রান দেই তাহলে দেখব আমাদের কোড কাজ করছে।

এভাবে, আমরা ~= অপারেটরকে overloading এর মাধ্যমে প্রায় যেকোনো টাইপের ক্ষেত্রে ব্যবহার করতে পারব। আজ এই পর্যন্তই।

Overloading ~=.playground ফাইল


0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.