प्रोग्रामिंग पैरेडाइम क्या है?
पैरेडाइम (paradigm) प्रोग्राम लिखने की एक शैली या सोचने का तरीक़ा है। एक ही सवाल अलग शैलियों में हल हो सकता है। कंप्यूटर को फ़र्क़ नहीं पड़ता; इंसान को पड़ता है, क्योंकि अच्छी शैली से प्रोग्राम पढ़ना, जाँचना और बदलना आसान होता है।
हमारा उदाहरण: 1 से 6 की सम संख्याओं के वर्ग जोड़ो। उत्तर: 2² + 4² + 6² = 4 + 16 + 36 = 56।
ज़्यादातर आधुनिक भाषाएँ (Python, JavaScript, Java) एक से ज़्यादा पैरेडाइम चलने देती हैं।
आदेशात्मक पैरेडाइम: आदेश और बदलते चर
आदेशात्मक (imperative) प्रोग्राम क्रम से आदेशों की सूची है। इसमें ऐसे चर होते हैं जिनके मान बदलते हैं। इस बदलते संचित डेटा को स्थिति (state) कहते हैं। आम साधन हैं क्रम, चयन (if) और लूप। जब आदेश नाम वाली प्रक्रियाओं में बाँटे जाएँ तो इसे प्रक्रियात्मक (procedural) कहते हैं।
total = 0
for n in range(1, 7):
if n % 2 == 0:
total = total + n * n
print(total) # 56ताक़त: कंप्यूटर के काम करने के तरीक़े के क़रीब और क़दम-दर-क़दम समझने में आसान। कमज़ोरी: बहुत सारे बदलते चरों से बड़े प्रोग्राम जाँचना कठिन हो जाता है।
फंक्शनल पैरेडाइम: फंक्शन अंदर, फंक्शन बाहर
फंक्शनल (functional) प्रोग्राम फंक्शनों से बनता है। शुद्ध फंक्शन (pure function) एक ही इनपुट पर हमेशा वही आउटपुट देता है और अपने बाहर कुछ नहीं बदलता (कोई साइड इफ़ेक्ट नहीं)। डेटा वहीं नहीं बदला जाता; नया मान बनता है (अपरिवर्तनीय डेटा)।
- filter जाँच पास करने वाली चीज़ें रखता है।
- map हर चीज़ पर एक ही काम करता है।
- fold (या reduce, sum) सब चीज़ों को जोड़कर एक मान बनाता है।
evens = filter(lambda n: n % 2 == 0, range(1, 7))
squares = map(lambda n: n * n, evens)
print(sum(squares)) # 56ताक़त: छोटा, जाँचने में आसान, कई काम साथ चलें तब भी सुरक्षित। कमज़ोरी: शुरू में अजीब लग सकता है और खेल की स्क्रीन जैसी बदलती चीज़ों के लिए हमेशा सबसे अच्छा नहीं।
ऑब्जेक्ट-आधारित पैरेडाइम: बात करने वाले ऑब्जेक्ट
ऑब्जेक्ट-आधारित (object-oriented) प्रोग्राम ऑब्जेक्टों से बनता है। हर ऑब्जेक्ट अपना डेटा (गुण/attributes) और अपने काम (मेथड/methods) रखता है। क्लास उसका नक़्शा है और ऑब्जेक्ट उससे बनते हैं। ऑब्जेक्ट संदेश भेजकर (मेथड बुलाकर) साथ काम करते हैं। डेटा को ऑब्जेक्ट के अंदर छिपाकर रखना एनकैप्सुलेशन है। नई क्लास पुरानी का उपयोग कर सकती है (इनहेरिटेंस)।
class Num:
def __init__(self, v): self.v = v
def is_even(self): return self.v % 2 == 0
def square(self): return self.v * self.v
class Sum:
def __init__(self): self.total = 0
def add(self, x): self.total += x
s = Sum()
for v in range(1, 7):
n = Num(v)
if n.is_even(): s.add(n.square())
print(s.total) # 56ताक़त: असली चीज़ों (खिलाड़ी, बैंक खाते, बटन) से मेल खाता है। कमज़ोरी: छोटे काम के लिए ज़रूरत से ज़्यादा कोड।
एक और पैरेडाइम: डिक्लेरेटिव और लॉजिक
डिक्लेरेटिव (declarative) प्रोग्राम बताता है कि क्या नतीजा चाहिए, कैसे पाना है यह नहीं। SQL इसका उदाहरण है: SELECT name FROM students WHERE marks > 90 यह नहीं बताता कि खोज कैसे हो। लॉजिक प्रोग्रामिंग (जैसे Prolog) में तुम तथ्य और नियम लिखते हो और सवाल पूछते हो; सिस्टम उत्तर ख़ुद खोजता है। फंक्शनल प्रोग्रामिंग को भी अक्सर डिक्लेरेटिव कहा जाता है।
घटना-आधारित (event-driven) प्रोग्राम घटनाओं (क्लिक, कुंजी) का इंतज़ार करता है और हर घटना पर कोड का एक टुकड़ा चलाता है। वेब पेज इसी तरह चलते हैं, अक्सर ऑब्जेक्टों के साथ।
किसी पैरेडाइम में प्रोग्राम लिखना और जाँचना
किसी पैरेडाइम में प्रोग्राम लिखने के लिए उसकी सोच अपनाओ:
- आदेशात्मक: क़दमों की सूची बनाओ, चरों के नाम रखो, लूप तय करो।
- फंक्शनल: काम को छोटे शुद्ध फंक्शनों में बाँटो और उन्हें पाइपलाइन में जोड़ो।
- ऑब्जेक्ट: "चीज़ें" खोजो, हर एक को डेटा और काम दो, तय करो कौन किसे संदेश भेजेगा।
अपने प्रोग्राम को जाँचने (evaluate) के लिए पूछो: क्या कई सूचियों पर उत्तर सही है? क्या पढ़ना आसान है? क्या जाँचना आसान है? क्या बाद में बिना बिगाड़े बदल सकता हूँ?
ट्रेसिंग मदद करती है: हर क़दम के बाद चरों के मान लिखो। ऊपर के आदेशात्मक कोड में total 0 → 4 → 20 → 56 होता है।
सवाल के लिए पैरेडाइम चुनना
कोई पैरेडाइम हर काम के लिए सबसे अच्छा नहीं। इन्हें तौलो:
- सवाल: डेटा बदलने के काम फंक्शनल को जँचते हैं; अपने-अपने व्यवहार वाली कई चीज़ें ऑब्जेक्ट को; आदेशों का कड़ा क्रम आदेशात्मक को।
- आकार और टीम: बड़ी टीमें साफ़ सीमाओं वाले ऑब्जेक्ट पसंद करती हैं।
- सुरक्षा और जाँच: शुद्ध फंक्शन जाँचने में सबसे आसान हैं।
- गति और मेमोरी: आदेशात्मक कोड मशीन के लिए सबसे सीधा हो सकता है।
- साधन और हुनर: वही चुनो जो भाषा और टीम जानती है।
असली प्रोग्राम शैलियाँ मिलाते हैं: ढाँचे के लिए ऑब्जेक्ट, हिसाब के लिए फंक्शन और मेथडों के अंदर आदेश।
मुख्य सूत्र और परिभाषाएँ
- आदेशात्मक = आदेश + बदलते चर (स्थिति)
- फंक्शनल = शुद्ध फंक्शन + अपरिवर्तनीय डेटा; filter → map → fold
- ऑब्जेक्ट-आधारित = क्लास → ऑब्जेक्ट (डेटा + मेथड) + संदेश
- डिक्लेरेटिव = बताओ क्या चाहिए, कैसे नहीं (SQL, Prolog)
- जाँच: 1..6 की सम संख्याओं के वर्गों का योग = 4 + 16 + 36 = 56
हल किए गए उदाहरण
1. सूची 1..6 के लिए आदेशात्मक प्रोग्राम का ट्रेस करो और हर सम संख्या के बाद total लिखो।
शुरू में total = 0। n = 2: total = 0 + 4 = 4। n = 4: total = 4 + 16 = 20। n = 6: total = 20 + 36 = 56। विषम 1, 3, 5 छोड़ दी जाती हैं।
2. [1, 2, 3, 4] के लिए "हर संख्या दुगनी करो, फिर 5 से बड़ी रखो" के फंक्शनल क़दम लिखो।
map दुगना करता है: [2, 4, 6, 8]। filter > 5 रखता है: [6, 8]। क्रम मायने रखता है: पहले map, फिर filter। मूल सूची [1, 2, 3, 4] नहीं बदली।
3. एक खेल में Player, Enemy और Coin हैं। कौन-सा पैरेडाइम जँचता है और हर एक क्या रख सकता है?
ऑब्जेक्ट-आधारित। Player: डेटा = जान, जगह; मेथड = चलना, कूदना। Enemy: डेटा = जान, गति; मेथड = पीछा करना, हमला। Coin: डेटा = मूल्य; मेथड = उठाना। वे "attack(player)" जैसे संदेश भेजते हैं।
4. वर्गों के योग वाले सवाल के तीनों हल एक-एक पंक्ति में तुलना करो।
आदेशात्मक: लूप चर total बदलता है। फंक्शनल: filter, map और fold उत्तर बनाते हैं, कोई चर नहीं बदलता। ऑब्जेक्ट: हर Num ऑब्जेक्ट अपना वर्ग निकालकर Sum ऑब्जेक्ट को भेजता है। तीनों का उत्तर 56।
आम गलतियाँ
- सोचना कि भाषा सिर्फ़ एक पैरेडाइम की होती है। Python और JavaScript यहाँ दिखाई सभी शैलियाँ चलने देती हैं।
- मान लेना कि फंक्शनल कोड हमेशा छोटा या तेज़ होता है। अक्सर छोटा होता है, पर गति सवाल पर निर्भर है।
- "ऑब्जेक्ट-आधारित" का मतलब सिर्फ़ ऑब्जेक्ट बनाना समझना। असली विचार डेटा और काम का साथ रहना और ऑब्जेक्टों के बीच संदेश है।
- पाइपलाइन में क्रम बिगाड़ना। पहले filter फिर map, पहले map फिर filter से अलग है।