C# में कार्यात्मक प्रोग्रामिंग: सिद्धांत से व्यवहार तक
कार्यात्मक प्रोग्रामिंग (FP) एक प्रतिमान है जिसमें गणनाओं को गणितीय फ़ंक्शनों की गणना के रूप में देखा जाता है, जिसमें स्थिति और परिवर्तनीय डेटा में बदलाव से बचा जाता है। हालाँकि C# मूल रूप से एक ऑब्जेक्ट-ओरिएंटेड भाषा थी, संस्करण 3.0 से इसने सक्रिय रूप से कार्यात्मक क्षमताओं को शामिल करना शुरू कर दिया। आज C# लैम्ब्डा एक्सप्रेशन, LINQ, अपरिवर्तनीय प्रकार और यहाँ तक कि pattern matching जैसी अवधारणाओं का समर्थन करता है। इस लेख में हम FP के प्रमुख सिद्धांतों को समझेंगे और दिखाएंगे कि उन्हें C# पर वास्तविक परियोजनाओं में कैसे लागू किया जाए।
1. शुद्ध फ़ंक्शन और दुष्प्रभावों का अभाव
शुद्ध फ़ंक्शन वह फ़ंक्शन है जो:
- समान तर्कों के लिए हमेशा एक ही परिणाम लौटाता है (संदर्भात्मक पारदर्शिता)।
- इसका कोई दुष्प्रभाव नहीं होता (वैश्विक स्थिति नहीं बदलता, फ़ाइलों में नहीं लिखता, HTTP अनुरोध नहीं भेजता)।
C# में एक शुद्ध फ़ंक्शन इस तरह दिख सकता है:
public static int Add(int a, int b) => a + b;और यहाँ एक अशुद्ध फ़ंक्शन का उदाहरण है:
public static int AddAndLog(int a, int b){ Console.WriteLine($"हम {a} और {b} को जोड़ रहे हैं"); // दुष्प्रभाव return a + b;}शुद्ध फ़ंक्शनों के लाभ: इनका परीक्षण, डिबगिंग और समानांतरीकरण आसान है।
2. अपरिवर्तनीयता (Immutability)
FP में डेटा डिफ़ॉल्ट रूप से अपरिवर्तनीय होता है। C# में इसके लिए उपयोग किया जाता है:
- फ़ील्ड के लिए कीवर्ड
readonly। recordसंरचनाएँ (C# 9+), जो स्वचालित रूप से अपरिवर्तनीय ऑब्जेक्ट बनाती हैं।- नेमस्पेस
System.Collections.Immutableसे संग्रह।
record के साथ उदाहरण:
public record Person(string Name, int Age);यदि आयु बदलने की आवश्यकता हो, तो एक नया इंस्टेंस बनाया जाता है:
Person person = new("इवान", 30);Person olderPerson = person with { Age = 31 };अपरिवर्तनीयता आकस्मिक उत्परिवर्तन को रोकती है और मल्टीथ्रेडिंग को सरल बनाती है।
3. उच्च-क्रम फ़ंक्शन और लैम्ब्डा एक्सप्रेशन
उच्च-क्रम फ़ंक्शन अन्य फ़ंक्शनों को तर्क के रूप में लेते हैं या उन्हें लौटाते हैं। C# में इसे डेलिगेट के माध्यम से कार्यान्वित किया जाता है: Func<>, Action<>, Predicate<>।
एक सरल उदाहरण — LINQ से Where विधि:
List<int> numbers = new() { 1, 2, 3, 4, 5 };var evenNumbers = numbers.Where(n => n % 2 == 0).ToList();यहाँ n => n % 2 == 0 एक लैम्ब्डा एक्सप्रेशन (अनाम फ़ंक्शन) है।
अपना स्वयं का उच्च-क्रम फ़ंक्शन लिखा जा सकता है:
public static List<T> Filter<T>(List<T> list, Func<T, bool> predicate){ var result = new List<T>(); foreach (var item in list) if (predicate(item)) result.Add(item); return result;}4. LINQ: कार्यात्मक शैली का शक्तिशाली उपकरण
LINQ (Language Integrated Query) शायद C# में कार्यात्मक प्रोग्रामिंग का सबसे उज्ज्वल उदाहरण है। यह SQL की तरह, संग्रहों को घोषणात्मक रूप से संसाधित करने की अनुमति देता है।
उदाहरण: 18 वर्ष से अधिक आयु के उपयोगकर्ताओं के नाम प्राप्त करें, जो आयु के अनुसार क्रमबद्ध हों:
var users = new List<User>{ new("अन्ना", 22), new("बोरिस", 17), new("विक्टर", 30)};
var result = users .Where(u => u.Age >= 18) .OrderBy(u => u.Age) .Select(u => u.Name) .ToList();LINQ विलंबित निष्पादन (lazy evaluation) का समर्थन करता है, जो संसाधनों की बचत करता है।
5. C# में मोनाड और Maybe-प्रकार
मोनाड संदर्भ के साथ गणनाओं की श्रृंखला के लिए एक अमूर्तता है (उदाहरण के लिए, null प्रसंस्करण या अतुल्यकालिकता)। C# में कोई अंतर्निहित Maybe मोनाड नहीं है, लेकिन इसे आसानी से कार्यान्वित किया जा सकता है:
public class Maybe<T>{ private readonly T _value; public bool HasValue { get; } p