जानिए कि जॉन मैककार्थी का प्रतीकात्मक दृष्टिकोण और लिस्प के डिजाइन विचार—लिस्ट, रिकर्सन, और गारबेज कलेक्शन—ने AI और आधुनिक प्रोग्रामिंग को कैसे प्रभावित किया।

यह "पुराने AI" का म्यूज़ियम टूर नहीं है। यह उन लोगों के लिए एक व्यावहारिक इतिहास है जो सॉफ़्टवेयर बनाते हैं—प्रोग्रामर, टेक लीड और प्रोडक्ट बिल्डर—क्योंकि जॉन मैककार्थी के विचारों ने यह प्रभावित किया कि हम प्रोग्रामिंग भाषाओं को किस लिए उपयोगी मानते हैं।
लिस्प केवल एक नया सिन्टैक्स नहीं था। यह एक दांव था कि सॉफ़्टवेयर विचारों को (सिर्फ़ संख्याओं को नहीं) मैनिपुलेट कर सकता है और भाषा डिज़ाइन के चुनाव रिसर्च, उत्पाद-इटरेशन और पूरे टूलिंग इकोसिस्टम को तेज कर सकते हैं।
मैककार्थी की विरासत को पढ़ने का एक उपयोगी तरीका यह सवाल है जो आज भी महत्वपूर्ण है: हम कितनी सीधे इरादा को एक निष्पादन योग्य सिस्टम में बदल सकते हैं—बिना बायलरप्लेट, घर्षण, या आकस्मिक जटिलता में डूबे? यह सवाल लिस्प के REPL से लेकर आधुनिक “chat-to-app” वर्कफ़्लो तक गूँजता है।
जॉन मैककार्थी को सिर्फ़ AI के शोधक्षेत्र की शुरुआत में मदद करने के लिए ही नहीं याद किया जाता, बल्कि इसलिए भी कि उन्होंने एक खास तरह के AI पर ज़ोर दिया: ऐसे सिस्टम जो विचारों को मैनिपुलेट कर सकें, केवल उत्तर गिनना नहीं। 1950 के दशक के मध्य में उन्होंने Dartmouth Summer Research Project आयोजित किया (जहाँ “artificial intelligence” शब्द प्रस्तावित हुआ) और बाद में MIT और Stanford में AI कार्य को आकार दिया। पर उनकी सबसे स्थायी योगदान शायद वह सवाल था जिसे वे बार-बार उठाते रहे: यदि तर्क को स्वयं एक प्रोग्राम के रूप में व्यक्त किया जा सके तो क्या होगा?
प्रारंभिक कंप्यूटिंग सफलताओं का अधिकतर हिस्सा संख्यात्मक था: बैलिस्टिक्स तालिकाएँ, इंजीनियरिंग सिमुलेशन, अनुकूलन और सांख्यिकी। ये समस्याएँ अंकगणित में अच्छी तरह फिट बैठती थीं।
मैककार्थी ने कुछ अलग लक्षित किया। मानवीय तर्क अक्सर ऐसे कॉन्सेप्ट्स के साथ काम करता है जैसे “यदि,” “क्योंकि,” “किसके अंतर्गत है,” “किस तरह का है,” और “वे सभी चीजें जो इन शर्तों को मिलती हैं।” ये चीजें फ़्लोटिंग‑पॉइंट मानों की तरह स्वाभाविक रूप से नहीं बैठतीं।
मैककार्थी का दृष्टिकोण ज्ञान को प्रतीकों (नाम, संबंध, श्रेणियाँ) की तरह मानता था और सोच को उन प्रतीकों पर निर्भरतावादी नियमों के रूप में—अर्थात् नियम-आधारित परिवर्तन—की तरह।
एक उच्च-स्तरीय तस्वीर यह है: संख्यात्मक तरीके “कितना?” का जवाब देते हैं जबकि प्रतीकात्मक तरीके “यह क्या है?” और “हम जो जानते हैं उससे क्या निकलता है?” जैसे प्रश्नों का उत्तर देने की कोशिश करते हैं।
जब आप मान लेते हैं कि तर्क को प्रोग्रामयोग्य बनाया जा सकता है, तो आपको एक ऐसी भाषा चाहिए जो सहज रूप से नियमों, तार्किक वक्तव्यों और नेस्टेड रिश्तों जैसी अभिव्यक्तियों को दर्शा सके—और फिर उन पर प्रक्रिया कर सके।
लिस्प को उसी लक्ष्य के लिए बनाया गया था। सख्त, पहले से बने डेटा स्ट्रक्चर में विचारों को ज़बरदस्ती ठूँसने की बजाय, लिस्प ने कोड और ज्ञान को एक समान आकार में प्रस्तुत करना आसान बनाया। यह सिर्फ़ शैक्षणिक शैली नहीं था—यह विचार का वर्णन और प्रक्रिया निष्पादन के बीच एक व्यावहारिक पुल था, जो मैककार्थी चाहता था कि AI पार करे।
जब मैककार्थी और प्रारंभिक AI शोधकर्ता “प्रतीकात्मक” कहते थे, तो उनका मतलब रहस्यमयी गणित नहीं था। एक प्रतीक बस एक अर्थपूर्ण लेबल है: customer जैसा नाम, hungry जैसा शब्द, या IF और THEN जैसे टैग। प्रतीक महत्वपूर्ण हैं क्योंकि वे एक प्रोग्राम को आइडिया (श्रेणियाँ, रिश्ते, नियम) के साथ काम करने देते हैं बजाय सिर्फ कच्ची संख्याओं के।
सरल रूप से: स्प्रेडशीट तब शानदार हैं जब आपकी दुनिया कॉलम और अंकगणित हो। प्रतीकात्मक सिस्टम तब बेहतरीन हैं जब आपकी दुनिया नियम, श्रेणियाँ, अपवाद और संरचना हो।
कई प्रोग्रामों में 42 और "age" के बीच फर्क डेटा प्रकार से ज़्यादा इस बात से होता है कि वह मान क्या दर्शाता है। एक प्रतीक आपको कुछ ऐसा देता है जिसे आप तुलना कर सकते हैं, स्टोर कर सकते हैं, और मिलाकर रख सकते हैं बिना अर्थ खोए।
इसलिए यह स्वाभाविक है कि आप “Paris एक शहर है” या “यदि बैटरी कम है, तो चार्जर ढूँढो” जैसी चीज़ों को दर्शाएँ।
कुछ उपयोगी करने के लिए आपके पास संरचना होनी चाहिए। लिस्प ने एक बहुत साधारण संरचना लोकप्रिय बनाई: लिस्ट। एक लिस्ट सिर्फ़ चीज़ों का एक क्रमबद्ध समूह है, और उन चीज़ों में से प्रत्येक खुद भी लिस्ट हो सकता है। इस एक विचार से आप वाक्य, फ़ॉर्म और पेड़-आकृति वाले ज्ञान का प्रतिनिधित्व कर सकते हैं।
यहाँ एक छोटा वैचारिक उदाहरण है (लिस्प-जैसी शैली में दिखाया गया):
(sentence (subject robot) (verb needs) (object power))
यह लगभग अंग्रेज़ी की तरह पढ़ता है: एक वाक्य जो subject, verb, और object से बना है। क्योंकि यह संरचित है, एक प्रोग्राम (subject robot) निकाल सकता है या (object power) को किसी और चीज़ से बदल सकता है।
एक बार जानकारी प्रतीकात्मक संरचनाओं में आ जाए, क्लासिक AI कार्यों को संभालना संभव हो जाता है:
कुंजी परिवर्तन यह है कि प्रोग्राम केवल गणना नहीं कर रहा; वह ज्ञान के अर्थपूर्ण टुकड़ों को ऐसे रूप में मैनिपुलेट कर रहा है जिसे वह निरीक्षण और परिवर्तित कर सके।
लिस्प के डिजाइन निर्णय अकादमिक दायरे तक सीमित नहीं रहे। उन्होंने लोगों के उपकरण बनाने और विचारों का तेजी से परीक्षण करने के तरीके को प्रभावित किया:
ये गुण ऐसे इकोसिस्टम बनाते हैं जहाँ प्रयोग सस्ता होता है, प्रोटोटाइप जल्दी उत्पाद बनते हैं, और टीमें ज़रूरत बदलने पर अनुकूलित हो सकती हैं।
लिस्प की शुरुआत एक बहुत व्यावहारिक समस्या से हुई: ऐसे प्रोग्राम कैसे लिखें जो संख्या की तरह सहज रूप से प्रतीकों के साथ काम कर सकें?
मैककार्थी ‘‘बेहतर कैलकुलेटर’’ बनाने की कोशिश नहीं कर रहे थे। वे ऐसी भाषा चाहते थे जहाँ (is (parent Alice Bob)) जैसी अभिव्यक्ति को (+ 2 3) जितनी आसानी से संग्रहीत, निरीक्षित, परिवर्तन और तर्क किया जा सके।
प्राथमिकता यह थी कि प्रतीकात्मक जानकारी को सरलता से दर्शाना और मैनिपुलेट करना आसान हो। इसने लिस्ट और पेड़ जैसी संरचनाओं पर ध्यान केंद्रित कराया, क्योंकि ये मनुष्यों द्वारा अर्थ व्यक्त करने के लिए पहले से उपयोग की जाने वाली चीज़ों—वाक्य, तार्किक नियम, नेस्टेड श्रेणियाँ, और रिश्तों—के अनुकूल हैं।
एक और लक्ष्य भाषा के कोर को छोटा और सुसंगत रखना था। जब भाषा में कम "विशेष मामले" होते हैं, तो आप नियम याद करने में कम समय बिताते हैं और विचारों को जोड़ने में अधिक। लिस्प ने कुछ छोटे बिल्डिंग ब्लॉक्स में निवेश किया जिन्हें बड़े एब्स्ट्रैक्शन्स में जोड़ा जा सके।
एक मुख्य अंतर्दृष्टि यह थी कि प्रोग्राम और डेटा एक ही तरह की संरचना साझा कर सकते हैं। सरल शब्दों में: यदि आपका डेटा नेस्टेड लिस्ट है, तो आपका प्रोग्राम भी नेस्टेड लिस्ट हो सकता है।
इसका मतलब:
लिस्प ने यह मानसिकता भी लोकप्रिय बनाई: भाषाएँ एक-आकार-सबके-लिए नहीं होनी चाहिए। वे समस्या डोमेन—जैसे तर्क, खोज और ज्ञान प्रतिनिधित्व—के चारों ओर डिज़ाइन की जा सकती हैं, और फिर भी दशकों तक सामान्य प्रयोजन प्रोग्रामिंग को प्रभावित कर सकती हैं।
S-एक्सप्रेशंस (symbolic expressions के लिए संक्षेप) लिस्प का चिन्हित विचार हैं: कोड और डेटा को नेस्टेड लिस्ट्स के रूप में प्रतिनिधित्व करने का एक सुसंगत तरीका।
एक नज़र में, S-एक्सप्रेशन सिर्फ़ आइटम्स के चारों ओर कोष्ठक हैं—कुछ आइटम एटम्स होते हैं (जैसे नाम और संख्याएँ), और कुछ आइटम स्वयं लिस्ट्स होते हैं। उस "लिस्ट के अंदर लिस्ट" नियम का पूरा मतलब यही है।
क्योंकि संरचना एकरूप है, लिस्प प्रोग्राम की रचना एकदम नीचे तक एक ही बिल्डिंग ब्लॉक्स से होती है। एक फ़ंक्शन कॉल, एक कॉन्फ़िगरेशन जैसा डेटा चंक, और प्रोग्राम संरचना का टुकड़ा—सब एक लिस्ट के रूप में व्यक्त किए जा सकते हैं।
यह सुसंगतता तुरंत लाभ देती है:
भले ही आप कभी Lisp न लिखें, यह डिज़ाइन सबक महत्वपूर्ण है: जब सिस्टम एक-दो अनुमानित रूपों से बना होता है, तो आप किनारों के मामलों से जूझने में कम समय बिताते हैं और ज़्यादा निर्माण करते हैं।
S-एक्सप्रेशंस संयोजन को प्रोत्साहित करते हैं क्योंकि छोटे, पठनीय टुकड़े स्वाभाविक रूप से बड़े टुकड़ों में मिलते जाते हैं। जब आपका प्रोग्राम "सिर्फ़ नेस्टेड लिस्ट्स" हो, तो विचारों को जोड़ना अक्सर एक अभिव्यक्ति को दूसरी के अंदर नेस्ट करना या पुन:उपयोगी भागों से लिस्ट असेंबल करना होता है।
यह आपको मॉड्यूलर शैली की ओर धकेलता है: आप छोटे ऑपरेशन्स लिखते हैं जो एक काम करते हैं, फिर उन्हें जोड़कर बड़ी मंशा व्यक्त करते हैं।
स्पष्ट नुकसान अपरिचितता है। कई नए लोगों के लिए कोष्ठकों-भरा सिन्टैक्स अजीब दिखता है।
पर लाभ है भविष्यवाणी: एक बार नेस्टिंग नियम समझ में आ जाएँ तो आप प्रोग्राम की संरचना पर भरोसे के साथ देख सकते हैं—और टूल भी कर सकते हैं। यही स्पष्टता कारण है कि S-एक्सप्रेशंस का प्रभाव लिस्प से बहुत आगे तक गया।
रिकर्सन को समझना रोज़मर्रा की रूपक से आसान है: गंदे कमरे की सफाई को छोटे “कमरों” में बाँटना। आप सब कुछ एक साथ हल करने की कोशिश नहीं करते। आप एक वस्तु उठाते हैं, उसे उसकी जगह रखते हैं, और फिर शेष पर वही कार्रवाई दोहराते हैं। कदम सरल हैं; शक्ति तब आती है जब आप उन्हें तब तक दोहराते हैं जब तक कुछ बच न जाए।
लिस्प इस विचार को अपनाता है क्योंकि इसका बहुत सा डेटा प्राकृतिक रूप से लिस्टों से बना होता है: एक लिस्ट में एक “पहली चीज़” और “बाकी” होती है। वह आकार रिकर्सिव सोच के लिए परफेक्ट बैठता है।
किसी लिस्ट को प्रोसेस करने के लिए, आप पहले तत्व को हैंडल करते हैं, फिर वही तर्क बाकी पर लागू करते हैं। जब लिस्ट खाली हो जाती है, आप रुकते हैं—यह साफ़ "कुछ बचा नहीं" क्षण है जो रिकर्सन को परिभाषित और रहस्यमयी नहीं बनाता।
मान लीजिए आप संख्याओं की एक लिस्ट का कुल चाहते हैं।
बस। परिभाषा अंग्रेज़ी जैसी लगती है, और प्रोग्राम संरचना विचार को प्रतिबिंबित करती है।
प्रतीकात्मक AI अक्सर अभिव्यक्तियों का प्रतिनिधित्व पेड़ के रूप में करता है (एक ऑपरेटर के साथ सब‑अभिव्यक्तियाँ)। रिकर्सन उस पेड़ पर “चलने” का स्वाभाविक तरीका है: बाईं भाग का वही तरीका लगाकर मूल्यांकन करें जैसा दाईं भाग का, और तब तक चलते रहें जब तक सरल मान न मिले।
इन पैटर्न्स ने बाद के फंक्शनल प्रोग्रामिंग को आकार दिया: छोटे फ़ंक्शन्स, स्पष्ट बेस केस, और डेटा ट्रांसफ़ॉर्मेशन जिन्हें समझना आसान है। Lisp के बाहर भी, "एक कदम करो, फिर शेष पर दोहराओ" की आदत साफ़ प्रोग्राम और कम साइड‑इफेक्ट वाले कोड की ओर ले जाती है।
प्रारंभिक प्रोग्रामरों को अक्सर मेमोरी मैन्युअली प्रबंधित करनी होती थी: स्पेस अलोकेट करना, किसके पास "मालिकाना" है ट्रैक करना, और सही समय पर उसे फ़्री करना याद रखना। यह काम सिर्फ़ विकास धीमा नहीं करता—यह एक ऐसी श्रेणी की बग भी उत्पन्न करता है जो पुनरुत्पादन में कठिन और शिप करने में आसान हैं: रिसाव जो धीरे-धीरे प्रदर्शन घटा देते हैं, और डैंगलिंग पॉइंटर्स जो कार्यक्रम को तब क्रैश कर देते हैं जब मूल गलती हुई थी।
जॉन मैककार्थी ने लिस्प के लिए गारबेज कलेक्शन पेश किया ताकि प्रोग्रामर अर्थ पर ध्यान दे सकें न कि बहीखाता पर।
उच्च स्तर पर, GC स्वचालित रूप से उन मेमोरी टुकड़ों को ढूँढता है जो रनिंग प्रोग्राम से अब पहुंच योग्य नहीं हैं—ऐसी वैल्यूज़ जिन्हें अब कभी भी उपयोग नहीं किया जा सकेगा—और उस स्पेस को पुनः प्राप्त कर लेता है।
"हमने हर ऑब्जेक्ट को बिल्कुल एक बार मुक्त किया क्या?" पूछने की जगह, GC प्रश्न बदल देता है: "क्या यह ऑब्जेक्ट अब भी पहुँच योग्य है?" अगर प्रोग्राम उसे नहीं पहुँच सकता, तो वह कचरा माना जाता है।
प्रतीकात्मक AI के काम में, लिस्प प्रोग्राम अक्सर बहुत सारी छोटी-अवधि वाली लिस्टें, ट्री और मध्यवर्ती परिणाम बनाते हैं। मैनुअल मेमोरी प्रबंधन प्रयोग को उन दिनों‑दिन की लड़ाई में बदल देता।
GC रोज़मर्रा के अनुभव को बदल देता है:
कुंजी विचार यह है कि भाषा सुविधा एक टीम गुणक हो सकती है: रहस्यमयी भ्रष्टाचार डिबग करने में कम घंटों का अर्थ है असली लॉजिक सुधारने में अधिक समय।
मैककार्थी का चुनाव सिर्फ़ लिस्प तक सीमित नहीं रहा। कई बाद की प्रणालियों ने GC और इसके वेरिएशन्स अपनाए क्योंकि यह व्यापार अक्सर खुद को चुकाता है: Java, C#, Python, JavaScript रनटाइम और Go सभी बड़े‑स्तर के विकास को सुरक्षित और तेज़ बनाने के लिए गारबेज कलेक्शन पर निर्भर करते हैं—यहाँ तक कि जब प्रदर्शन प्राथमिकता हो।
लिस्प में एक अभिव्यक्ति एक सुसंगत आकार में लिखा गया कोड का टुकड़ा है (अक्सर लिस्ट)। इवैल्युएशन बस वह प्रक्रिया है जो तय करती है कि वह अभिव्यक्ति "क्या मतलब रखती है" और "क्या उत्पन्न करती है"।
उदाहरण के लिए, जब आप लिखते हैं "इन संख्याओं को जोड़ो" या "इस फ़ंक्शन को इन इनपुट्स के साथ कॉल करो", तो इवैल्युएटर कुछ नियमों का पालन करके उस अभिव्यक्ति को परिणाम में बदल देता है। इसे भाषा का रेफरी समझिये: यह तय करता है अगला कदम क्या है, किस क्रम में करना है, और कब रुकना है।
मैककार्थी की कुंजी सिर्फ़ नया सिंटैक्स आविष्कार करना नहीं थी—बल्कि "अर्थ इंजन" को कॉम्पैक्ट और नियमित रखना भी था। जब इवैल्युएटर कुछ स्पष्ट नियमों से बना होता है, तो दो अच्छी चीजें होती हैं:
यह सुसंगतता इसीलिए लिस्प को प्रतीकात्मक AI में विचारों का प्
प्रतीकात्मक सोच सीधे तौर पर धारणाओं और संबंधों को दर्शाती है (जैसे “customer”, “is-a”, “depends-on”, “if…then…”), और फिर उन प्रतिनिधियों पर नियम व रूपांतरण लागू करती है।
यह तब सबसे उपयोगी है जब आपका समस्या क्षेत्र ढाँचा, अपवाद और अर्थ से भरा हो—जैसे नियम इंजन, योजना बनाना, कंपाइलर, कॉन्फ़िगरेशन या वर्कफ़्लो लॉजिक—न कि सिर्फ़ अंकगणितीय गणनाओं के लिए।
मैककार्थी ने यह विचार जोर देकर रखा कि तर्क को प्रोग्राम के रूप में व्यक्त किया जा सकता है—केवल गणना नहीं।
इस नज़रिए ने प्रभावित किया:
लिस्ट "भागों से बनी चीज़ों" को दर्शाने का एक न्यूनतम, लचीला तरीका है। क्योंकि लिस्ट के तत्व खुद लिस्ट हो सकते हैं, आपको स्वाभाविक रूप से ट्री संरचनाएँ मिल जाती हैं।
इससे आसानी से हो पाता है:
S-एक्सप्रेशंस आपको कोड और डेटा के लिए एक समान रूप देते हैं: नेस्टेड लिस्ट्स।
यह समानता कई मायनों में सिस्टम को सरल बनाती है:
मैक्रो दोहराए जाने वाले कोड संरचनाओं को स्वचालित करते हैं, न कि केवल गणना को।
मैक्रो का प्रयोग तब करें जब आप चाहते हैं:
यदि आपको केवल पुन:उपयोगी लॉजिक चाहिए, तो आम तौर पर फ़ंक्शन बेहतर विकल्प है।
गारबेज कलेक्शन (GC) उन मेमोरी टुकड़ों को स्वचालित रूप से मुक्त कर देता है जो रनिंग प्रोग्राम से पहुँच योग्य नहीं हैं—इससे गलती की विशेष श्रेणियाँ (डैंगलिंग पॉइंटर्स, डबल-फ्री) बहुत घट जाती हैं।
यह खासकर तब मददगार है जब आपका प्रोग्राम कई अस्थायी स्ट्रक्चर (लिस्ट/ट्री/इंटरमीडियेट रिज़ल्ट) बनाता है, क्योंकि आप बिना मैनुअल मेमोरी-ओनरशिप योजना के प्रोटोटाइप और रिफैक्टर कर सकते हैं।
REPL “सोचो → आज़माओ → देखें” लूप को संकुचित कर देता है। आप एक फ़ंक्शन डिफ़ाइन कर सकते हैं, उसे कुछ इनपुट से चला कर तुरंत बदलकर फिर चला सकते हैं।
गैर-Lisp स्टैक्स में इसी लाभ को अपनाने के लिए:
संबंधित पढ़ाई: /blog/the-repl-and-fast-feedback-loops
कई आधुनिक वर्कफ़्लोज़ वही मूल विचार फिर से इस्तेमाल करते हैं:
map/filter, composition)भले ही आप Lisp कभी न चलाएँ, आप संभवतः रोज़मर्रा में Lisp-से आए आदतों का उपयोग करते हैं।
वास्तविक ट्रेड-ऑफ़ इस तरह हैं:
व्यावहारिक तरीका यह है कि प्रतिष्ठान के आधार पर फिट का मूल्यांकन करें, साख पर नहीं।
यह 10-मिनट अभ्यास आज़माएँ:
यह अक्सर दिखाता है कि कहाँ “कोड-एज-डेटा” पैटर्न, नियम इंजन, या DSL-सदृश कॉन्फ़िग फायदेमंद होंगे।