C++ में कार्यात्मक प्रोग्रामिंग: A से Z तक
\n\nकई डेवलपर्स, जो Python या JavaScript से परिचित हैं, कार्यात्मक प्रोग्रामिंग के शक्तिशाली टूल्स जैसे लैम्ब्डा, map, filter, reduce के आदी हैं। लेकिन क्या आप जानते हैं कि C++ कार्यात्मक शैली के लिए समान रूप से लचीली क्षमताएँ प्रदान करता है? इस लेख में हम C++ में कार्यात्मक प्रोग्रामिंग को बुनियादी अवधारणाओं से लेकर उन्नत तकनीकों तक समझेंगे। आप सीखेंगे कि C++11/14/17 की आधुनिक क्षमताओं का उपयोग करके अधिक संक्षिप्त, सुरक्षित और अभिव्यंजक कोड कैसे लिखें।
\n\n1. कार्यात्मक दृष्टिकोण के मूल सिद्धांत: लैम्ब्डा एक्सप्रेशन और std::function
\n\nC++ में कार्यात्मक प्रोग्रामिंग लैम्ब्डा एक्सप्रेशन से शुरू होती है। वे आपको उपयोग के बिंदु पर ही अनाम फ़ंक्शन बनाने की अनुमति देते हैं। लैम्ब्डा का सिंटैक्स सरल है:
\n\n// बेसिक लैम्ब्डा\nauto sum = [](int a, int b) -> int { return a + b; };\nstd::cout << sum(5, 3); // 8\n\n// वेरिएबल कैप्चर के साथ लैम्ब्डा\nint multiplier = 3;\nauto multiply = [multiplier](int x) { return x * multiplier; };\nstd::cout << multiply(7); // 21\n\nलैम्ब्डा की मुख्य विशेषता संदर्भ कैप्चर करना है। आप वेरिएबल को मान द्वारा ([=]), संदर्भ द्वारा ([&]) या संयुक्त रूप से कैप्चर कर सकते हैं। यह क्लोजर का आधार है, जो कार्यात्मक शैली की नींव है।
लैम्ब्डा को संग्रहीत और पास करने के लिए std::function का उपयोग किया जाता है — कॉल करने योग्य ऑब्जेक्ट के लिए एक बहुरूपी आवरण:
#include <functional>\n\nstd::function<int(int, int)> operation;\n\noperation = [](int a, int b) { return a + b; };\nstd::cout << operation(10, 20); // 30\n\noperation = [](int a, int b) { return a * b; };\nstd::cout << operation(10, 20); // 200\n\nसुझाव: यदि लैम्ब्डा को प्रकार के रूप में संग्रहीत करने की आवश्यकता नहीं है, तो auto का उपयोग करें। std::function थोड़ा ओवरहेड जोड़ता है, इसलिए इसे केवल बहुरूपता की आवश्यकता होने पर ही उपयोग करें।
2. STL एल्गोरिदम: map, filter, reduce स्वयं बनाएं
\n\nC++ में Python की तरह बिल्ट-इन map, filter, reduce फ़ंक्शन नहीं हैं, लेकिन STL शक्तिशाली एल्गोरिदम प्रदान करता है जो उन्हें बदल देते हैं। आइए मुख्य एल्गोरिदम देखें:
2.1. Map — तत्वों का रूपांतरण
\nmap के बजाय std::transform का उपयोग करें:
#include <algorithm>\n#include <vector>\n\nstd::vector<int> numbers = {1, 2, 3, 4, 5};\nstd::vector<int> squares(numbers.size());\n\nstd::transform(numbers.begin(), numbers.end(), squares.begin(),\n [](int n) { return n * n; });\n// squares: {1, 4, 9, 16, 25}\n\n2.2. Filter — शर्त के अनुसार फ़िल्टर करना
\nfilter का एनालॉग — std::copy_if या std::remove_if (बाद में हटाने के साथ):
std::vector<int> numbers = {1, 2, 3, 4, 5, 6};\nstd::vector<int> evens;\n\nstd::copy_if(numbers.begin(), numbers.end(),\n std::back_inserter(evens),\n [](int n) { return n % 2 == 0; });\n// evens: {2, 4, 6}\n\n2.3. Reduce — संग्रह का संक्षेपण
\nreduce के लिए <numeric> से std::accumulate का उपयोग करें:
#include <numeric>\n\nstd::vector<int> numbers = {1, 2, 3, 4, 5};\nint sum = std::accumulate(numbers.begin(), numbers.end(), 0,\n [](int acc, int n) { return acc + n; });\n// sum = 15\n\nउन्नत उदाहरण: डेटा प्रोसेसिंग के लिए map, filter और reduce को संयोजित करें:
\n\nstd::vector<std::string> names = {"Alice", "Bob", "Charlie", "David"};\n// 'A' या 'C' से शुरू होने वाले नामों की लंबाई का योग प्राप्त करें\nint result = std::accumulate(names.begin(), names.end(), 0,\n [](int acc, const std::string& name) {\n if (name[0] == 'A' || name[0] == 'C') {\n return acc + name.length();\n }\n return acc;\n