Swift তার স্ট্যান্ডার্ড লাইব্রেরিতে প্রচুর সুবিধা দেয়, তবে বাহ্যিক লাইব্রেরি ও ফ্রেমওয়ার্ক ইমপোর্ট করে আপনি আরও অনেক ফিচার ব্যবহার করতে পারেন। এই মডিউলগুলো সরাসরি Swift প্রকল্প থেকে আসতে পারে (Swift Argument Parser-এর মতো), Apple প্ল্যাটফর্মের ফ্রেমওয়ার্ক থেকে (Foundation ও Network Framework-এর মতো), অথবা থার্ড-পার্টি ওপেন সোর্স লাইব্রেরি থেকে (SwiftyBeaver-এর মতো)।
Foundation-এর মতো কোর মডিউলগুলো, যা Swift-এর সবচেয়ে বেশি ব্যবহৃত লাইব্রেরিগুলোর একটি, Swift টুলচেইনের সাথে আসে। থার্ড-পার্টি লাইব্রেরি ইমপোর্ট করার আগে সেগুলোকে আপনার প্রকল্পের কনফিগারেশনে যোগ করতে হয় (যেমন Swift Package Manager ব্যবহার করে)।
মডিউল ইমপোর্ট করা হয় import কিওয়ার্ড লিখে, তার পরে মডিউলের নাম লিখে।
তাই প্রোগ্রামে নিচের লাইনটি যোগ করে Foundation ইমপোর্ট করা যায়।
import Foundation
একটি মডিউল ইমপোর্ট করলে তার টাইপ, মেথড ও ফাংশন আপনার কোডের জন্য উপলব্ধ হয়।
যেমন, Foundation ইমপোর্ট করলে String-এ components(separatedBy:)-এর মতো কাজের ইউটিলিটি মেথড যুক্ত হয়।
প্রচলিত রীতি অনুসারে import স্টেটমেন্টগুলো Swift ফাইলের শুরুতে রাখা হয়, যাতে কোড পড়ছে যে কেউই নির্ভরতাগুলো সঙ্গে সঙ্গে দেখতে পায়।
অ্যারের সাথে ব্যবহৃত সাবস্ক্রিপ্ট পদ্ধতি ব্যবহার করে String-এর প্রতিটি ক্যারেক্টার অ্যাক্সেস করা যায়।
তবে স্ট্রিংয়ের জন্য ব্যবহৃত ইনডেক্সগুলো ইন্টিজার নয় এবং সরাসরি এগুলো নিয়ে কাজ করা যায় না।
বরং এগুলো অন্য কোনো জানা ইনডেক্স, যেমন startIndex-এর ওপর ভিত্তি করে হিসাব করতে হয়। startIndex একটি খালি নয় এমন স্ট্রিংয়ের প্রথম ক্যারেক্টারের অবস্থান বোঝায়। এই হিসাবের জন্য String ও NSString লাইব্রেরিতে থাকা মেথডগুলো ব্যবহার করা যায় (Foundation মডিউল ইমপোর্ট করা থাকলে Swift-এর স্ট্রিংগুলো NSString-এর সব প্রপার্টি ও মেথড ব্যবহার করতে পারে)।
উদাহরণস্বরূপ, নিচের স্ট্রিংটি ধরুন:
let csv = "apple,pear,peach,orange,cherry,lime,goosberry"
"orange"-এর "g" পেতে কেউ csv[21] লিখতে পারে না, বরং String.Index টাইপের একটি মান হিসাব করে সেটি দিতে হয়।
লক্ষ্য করুন, এই ইনডেক্সগুলো এমনিতে মানুষের পড়ার জন্য বানানো নয়।
এগুলোকে অপাক ইনডেক্স বলা হয়, কারণ ভেতরে কী আছে তা মানুষকে জানতে হয় না।
let index = csv.index(csv.startIndex, offsetBy: 21)
csv[index]
// "g"
print(index)
// prints Index(_rawBits: 1376513)
তবে মনে রাখবেন, অফসেট যদি বৈধ ইনডেক্স না হয়, অর্থাৎ যদি তা startIndex-এর আগে বা endIndex-এর পরে ইনডেক্স দেয়, তাহলে অপারেশনটি এরর উত্থাপন করবে এবং প্রোগ্রামটি ক্র্যাশ করবে।
এই সমস্যা এড়াতে একটি সীমা নির্ধারণকারী ইনডেক্স উল্লেখ করা যায়।
এটি একটি অপশনাল ইনডেক্স রিটার্ন করে, আর অন্যথায় অবৈধ ইনডেক্সের ক্ষেত্রে nil রিটার্ন করবে।
let tooFar = csv.index(csv.startIndex, offsetBy: 200)
// error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
let tooFarButSafe = csv.index(csv.startIndex, offsetBy: 200, limitedBy: csv.endIndex)
// nil
এছাড়া, একটি স্ট্রিংয়ের ইনডেক্স অন্য স্ট্রিংয়ে ব্যবহার করা যায় না।
উদাহরণস্বরূপ, উপরে হিসাব করা "orange"-এর "g"-এর index দিয়ে fam = "This is my family: 👨👩👦👦, this is our dog: 🐶, this is our cat: 🐱!" স্ট্রিংয়ে ইনডেক্স করলে, অর্থাৎ fam[index] লিখলে আপনার প্রোগ্রাম ক্র্যাশ করবে।
এর পেছনে অনেক কারণ আছে, তবে মূলত সবই দাঁড়ায় একটাই কথা: "ইউনিকোড জটিল"।
সাধারণভাবে বলতে গেলে, যদি আলাদা আলাদা ক্যারেক্টারে র্যান্ডম অ্যাক্সেস দরকার হয়, তাহলে সম্ভবত Array<Character>-এর মতো অন্য কোনো ডেটা স্ট্রাকচার ব্যবহার করা উচিত।
স্ট্রিংয়ের প্রথম ও শেষ ক্যারেক্টার পেতে Swift-এ first ও last মেথড আছে।
এই মেথডগুলো একটি অপশনাল ক্যারেক্টার রিটার্ন করে, তাই স্ট্রিং খালি হলে তারা nil রিটার্ন করবে।
let str = "Hello, world!"
print(str.first) // Prints Optional("H")
print(str.last) // Prints Optional("!")
স্ট্রিংয়ের একটি সাবস্ট্রিং পেতেও prefix ও suffix মেথড ব্যবহার করতে পারেন।
এই মেথডগুলো একটি ইন্টিজার আর্গুমেন্ট নেয় এবং স্ট্রিংয়ের প্রথম বা শেষ n ক্যারেক্টার নিয়ে গঠিত একটি সাবস্ট্রিং রিটার্ন করে।
let str = "Hello, world!"
print(str.prefix(5)) // Prints "Hello"
print(str.suffix(6)) // Prints "world!"
প্রোগ্রামিংয়ে টেক্সট নিয়ে কাজ করা একটি কমন কাজ। Swift, Foundation ফ্রেমওয়ার্কসহ, স্ট্রিং পরীক্ষা, রূপান্তর ও ম্যানিপুলেশনের জন্য অনেক সুবিধাজনক মেথড ও প্রপার্টি দেয়।
components(separatedBy:) দিয়ে স্ট্রিং ভাগ করাকোনো ডিলিমিটার অনুসারে একটি স্ট্রিংকে সাবস্ট্রিংয়ের অ্যারেতে ভাগ করতে components(separatedBy:) ব্যবহার করুন (এজন্য Foundation ইমপোর্ট করা লাগে):
import Foundation
let sentence = "Hello, world!"
let words = sentence.components(separatedBy: " ")
print(words) // Prints ["Hello,", "world!"]
hasPrefix(_:) ও hasSuffix(_:) দিয়ে প্রিফিক্স ও সাফিক্স পরীক্ষা করাএকটি স্ট্রিং নির্দিষ্ট ক্যারেক্টারের একটি সিকোয়েন্স দিয়ে শুরু বা শেষ হয় কি না পরীক্ষা করতে hasPrefix(_:) ও hasSuffix(_:) ব্যবহার করুন:
let greeting = "Hello, world!"
print(greeting.hasPrefix("Hello")) // Prints true
print(greeting.hasSuffix("world!")) // Prints true
এই স্ট্যান্ডার্ড মেথড ও প্রপার্টিগুলো ব্যবহার করে স্ট্রিংয়ের কেস রূপান্তর করতে পারেন:
lowercased(): স্ট্রিংয়ের ছোট হাতের অক্ষরে লেখা একটি কপি রিটার্ন করে।uppercased(): স্ট্রিংয়ের বড় হাতের অক্ষরে লেখা একটি কপি রিটার্ন করে।capitalized: প্রতি শব্দের প্রথম অক্ষর বড় হাতের করে লেখা একটি কপি রিটার্ন করে (Foundation থেকে)।let greeting = "hello, world!"
print(greeting.lowercased()) // Prints "hello, world!"
print(greeting.uppercased()) // Prints "HELLO, WORLD!"
print(greeting.capitalized) // Prints "Hello, World!"
replacingOccurrences(of:with:) দিয়ে সাবস্ট্রিং প্রতিস্থাপন করাএকটি লক্ষ্য সাবস্ট্রিংয়ের সব উপস্থিতি অন্য একটি স্ট্রিং দিয়ে প্রতিস্থাপন করতে replacingOccurrences(of:with:) ব্যবহার করুন (Foundation থেকে):
let greeting = "Hello, world!"
let updated = greeting.replacingOccurrences(of: "world", with: "Swift")
print(updated) // Prints "Hello, Swift!"
joined(separator:) দিয়ে স্ট্রিং জোড়া দেওয়াjoined(separator:) মেথডটি [String]-এর মতো স্ট্রিংয়ের কালেকশনের অন্তর্গত।
এটি একটি সেপারেটর ব্যবহার করে এলিমেন্টগুলোকে জোড়া দিয়ে একটি স্ট্রিং বানায়:
let words = ["Hello", "world"]
let sentence = words.joined(separator: ", ")
print(sentence) // Prints "Hello, world"
শহরে নতুন একটি কবিতা ক্লাব খুলেছে, আর আপনি সেখানে যাওয়ার কথা ভাবছেন। আগে বেশ কিছু ঘটনা ঘটেছে, তাই ক্লাবে ঢোকার চেষ্টা করার আগে দরজার একটি খুব নির্দিষ্ট নিয়ম আপনাকে ভালোভাবে শিখে নিতে হবে।
কবিতা ক্লাবে দুটি দরজা আছে, দুটোতেই পাহারাদার রয়েছে। ভিতরে ঢুকতে হলে সেদিনের পাসওয়ার্ড আপনাকে বের করতে হবে:
প্রথমে আপনাকে কবিতাটিকে আলাদা আলাদা লাইনে ভাগ করতে হবে। পাহারাদার একটি কবিতা আবৃত্তি করবেন, আর আপনাকে সেটিকে লাইনে ভাগ করতে হবে।
splitOnNewlines ফাংশনটি লিখুন, যা একটি স্ট্রিং নেয় এবং নতুন লাইন অক্ষরকে ডেলিমিটার হিসেবে ব্যবহার করে সেটিকে স্ট্রিংয়ের অ্যারেতে ভাগ করে।
ফাংশনটি স্ট্রিংয়ের একটি অ্যারে রিটার্ন করবে, যেখানে প্রতিটি স্ট্রিং কবিতার একটি লাইন।
splitOnNewlines("Hello.\nHow are you?\n\nI'm doing fine.")
// returns ["Hello." ,"How are you?", "", "I'm doing fine"].
_ ব্যবহার করবেন।উদাহরণস্বরূপ, তাঁদের প্রিয় লেখকদের একজন মাইকেল লকউড নিচের অ্যাক্রোস্টিক কবিতাটি লিখেছেন, যার অর্থ হলো প্রতিটি বাক্যের প্রথম অক্ষর মিলে একটি শব্দ তৈরি করে:
Stands so high
Huge hooves too
Impatiently waits for
Reins and harness
Eager to leave
পাহারাদার কবিতাটি আবৃত্তি করলে আপনি সেটিকে আলাদা আলাদা লাইনে ভাগ করবেন এবং প্রতিটি লাইনের প্রথম অক্ষর দিয়ে উত্তর দেবেন, অর্থাৎ ["S", "H", "I", "R", "E"]।
এরপর পাহারাদার আপনার দেওয়া অক্ষরের অ্যারে থেকে তৈরি শব্দটি দেবেন, যাতে আপনি সেটিকে বড় হাতের অক্ষরের শব্দে রূপান্তর করেন।
সবশেষে আপনি যে পাসওয়ার্ড রিটার্ন করবেন তা হলো "SHIRE", এবং আপনি ভিতরে ঢুকে যাবেন।
frontDoorPassword ফাংশনটি লিখুন, যা কবিতাটি বোঝানো একটি স্ট্রিং নেয়।
ফাংশনটি সেই পাসওয়ার্ড রিটার্ন করবে যা আপনি পাহারাদারকে দেবেন।
frontDoorPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nReins and harness\nEager to leave")
// returns "SHIRE"
ক্লাবের পিছনে পাবেন সবচেয়ে নামকরা কবিদের, যা অনেকটা VIP এলাকার মতো। যেহেতু এটা সবার জন্য নয়, পিছনের দরজার প্রক্রিয়াটি একটু বেশি জটিল।
", please" যোগ করতে হবে।উদাহরণস্বরূপ, আগে উল্লেখ করা কবিতাটি আবার _টেলেস্টিক_ও, যার অর্থ হলো প্রতিটি বাক্যের শেষ অক্ষর মিলে একটি শব্দ তৈরি করে:
Stands so high
Huge hooves too
Impatiently waits for
Reins and harness
Eager to leave
পাহারাদার কবিতাটি আবৃত্তি করলে আপনি সেটিকে আলাদা আলাদা লাইনে ভাগ করবেন, পেছনের বাড়তি স্পেসগুলো সরিয়ে ফেলবেন এবং প্রতিটি লাইনের প্রথম অক্ষর দিয়ে উত্তর দেবেন, অর্থাৎ ["h", "o", "r", "s", "e"]।
এরপর পাহারাদার আপনার দেওয়া অক্ষরের অ্যারে থেকে তৈরি শব্দটি দেবেন, যাতে আপনি সেটিকে বড় হাতের অক্ষরের শব্দে রূপান্তর করেন এবং শেষে ", please" যোগ করেন।
সবশেষে আপনি যে পাসওয়ার্ড রিটার্ন করবেন তা হলো "horse, please", এবং আপনি ভিতরে ঢুকে যাবেন।
backDoorPassword ফাংশনটি লিখুন, যা কবিতাটি বোঝানো একটি স্ট্রিং নেয়।
ফাংশনটি সেই পাসওয়ার্ড রিটার্ন করবে যা আপনি পাহারাদারকে দেবেন।
backDoorPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nReins and harness\nEager to leave")
// returns "horse, please"
ক্লাবের পিছনের কক্ষের ভিতরে আরেকটি দরজা আছে, যা নিয়ে যায় গোপন কক্ষে, যেখানে কেবল সবচেয়ে সেরা কবিরাই ঢুকতে পারেন।
"!" যোগ করতে হবে।উদাহরণস্বরূপ, আগে উল্লেখ করা কবিতার একটি পরিবর্তিত রূপ এই নিয়মের সাথে মেলে:
Stands so high
Huge hooves too
Impatiently waits for
Rider with harness
Eager to leave
পাহারাদার কবিতাটি আবৃত্তি করলে আপনি সেটিকে আলাদা আলাদা লাইনে ভাগ করবেন, পেছনের বাড়তি স্পেসগুলো সরিয়ে ফেলবেন এবং প্রতিটি লাইনের ith অক্ষর দিয়ে উত্তর দেবেন, অর্থাৎ ["S", "u", "p", "e", "r"]।
এরপর পাহারাদার আপনার দেওয়া অক্ষরের অ্যারে থেকে তৈরি শব্দটি দেবেন, যাতে আপনি সেটিকে বড় হাতের অক্ষরের শব্দে রূপান্তর করেন এবং শেষে "!" যোগ করেন।
সবশেষে আপনি যে পাসওয়ার্ড রিটার্ন করবেন তা হলো SUPER!, এবং আপনি ভিতরে ঢুকে যাবেন।
secretRoomPassword ফাংশনটি লিখুন, যা কবিতাটি বোঝানো একটি স্ট্রিং নেয়।
ফাংশনটি সেই পাসওয়ার্ড রিটার্ন করবে যা আপনি পাহারাদারকে দেবেন।
secretRoomPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nRider with harness\nEager to leave")
// returns "SUPER!"
Exercism-এ সাইন আপ করুন, Swift ট্র্যাকের 35টি কনসেপ্ট116টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।