नर्ड्स का बदला

स्टार्टअप शुरू करना चाहते हैं? Y Combinator द्वारा फंड प्राप्त करें।


मई 2002

| "हम C++ प्रोग्रामर्स के पीछे थे। हमने उनमें से कई को लिस्प की ओर लगभग आधा रास्ता खींच लिया।"

  • गाय स्टील, जावा स्पेक के सह-लेखक

सॉफ़्टवेयर व्यवसाय में नुकीले सिर वाले शिक्षाविदों, और एक समान रूप से दुर्जेय शक्ति, नुकीले बालों वाले मालिकों के बीच एक निरंतर संघर्ष है। हर कोई जानता है कि नुकीले बालों वाला मालिक कौन है, है ना? मुझे लगता है कि प्रौद्योगिकी दुनिया में अधिकांश लोग न केवल इस कार्टून चरित्र को पहचानते हैं, बल्कि अपनी कंपनी में उस वास्तविक व्यक्ति को भी जानते हैं जिस पर यह आधारित है।

नुकीला बालों वाला मालिक चमत्कारिक रूप से दो गुणों को जोड़ता है जो अपने आप में आम हैं, लेकिन एक साथ शायद ही कभी देखे जाते हैं: (ए) वह तकनीक के बारे में कुछ भी नहीं जानता है, और (बी) उसके बारे में बहुत मजबूत राय है।

मान लीजिए, उदाहरण के लिए, आपको सॉफ़्टवेयर का एक टुकड़ा लिखने की आवश्यकता है। नुकीले बालों वाले मालिक को कोई अंदाज़ा नहीं है कि यह सॉफ़्टवेयर कैसे काम करना चाहिए, और वह एक प्रोग्रामिंग भाषा को दूसरी से अलग नहीं बता सकता है, फिर भी वह जानता है कि आपको इसे किस भाषा में लिखना चाहिए। बिल्कुल। उसे लगता है कि आपको इसे जावा में लिखना चाहिए।

उसे ऐसा क्यों लगता है? आइए नुकीले बालों वाले मालिक के दिमाग में झाँकें। वह जो सोच रहा है वह कुछ इस तरह है। जावा एक मानक है। मुझे पता है कि यह होना चाहिए, क्योंकि मैं इसके बारे में प्रेस में हर समय पढ़ता हूं। चूंकि यह एक मानक है, इसलिए इसका उपयोग करने के लिए मुझे कोई परेशानी नहीं होगी। और इसका मतलब यह भी है कि हमेशा बहुत सारे जावा प्रोग्रामर होंगे, इसलिए यदि मेरे लिए काम करने वाले प्रोग्रामर अब छोड़ देते हैं, जैसा कि मेरे लिए काम करने वाले प्रोग्रामर रहस्यमय ढंग से हमेशा करते हैं, तो मैं उन्हें आसानी से बदल सकता हूं।

ठीक है, यह इतना अनुचित नहीं लगता है। लेकिन यह सब एक अनकही धारणा पर आधारित है, और वह धारणा गलत साबित होती है। नुकीला बालों वाला मालिक मानता है कि सभी प्रोग्रामिंग भाषाएं काफी हद तक समतुल्य हैं। यदि वह सच होता, तो वह बिल्कुल सही होता। यदि भाषाएं सभी समतुल्य हैं, तो निश्चित रूप से, जो भी भाषा हर कोई उपयोग कर रहा है उसका उपयोग करें।

लेकिन सभी भाषाएं समतुल्य नहीं हैं, और मुझे लगता है कि मैं आपको उनके बीच के अंतरों में जाए बिना भी इसे साबित कर सकता हूं। यदि आप 1992 में नुकीले बालों वाले मालिक से पूछते कि सॉफ्टवेयर किस भाषा में लिखा जाना चाहिए, तो वह आज की तरह ही बिना किसी हिचकिचाहट के जवाब देता। सॉफ्टवेयर C++ में लिखा जाना चाहिए। लेकिन अगर भाषाएं सभी समतुल्य हैं, तो नुकीले बालों वाले मालिक की राय कभी क्यों बदलनी चाहिए? वास्तव में, जावा के डेवलपर्स को एक नई भाषा बनाने की परेशानी क्यों उठानी पड़ी?

मान लीजिए, यदि आप एक नई भाषा बनाते हैं, तो यह इसलिए है क्योंकि आपको लगता है कि यह किसी तरह से उन चीजों से बेहतर है जो लोगों के पास पहले से थीं। और वास्तव में, गॉस्लिंग पहले जावा व्हाइट पेपर में स्पष्ट करता है कि जावा को C++ के साथ कुछ समस्याओं को ठीक करने के लिए डिज़ाइन किया गया था। तो यह आपके पास है: भाषाएं सभी समतुल्य नहीं हैं। यदि आप नुकीले बालों वाले मालिक के दिमाग के माध्यम से जावा तक और फिर जावा के इतिहास के माध्यम से उसकी उत्पत्ति तक निशान का पालन करते हैं, तो आप एक ऐसे विचार के साथ समाप्त होते हैं जो उस धारणा का खंडन करता है जिससे आपने शुरुआत की थी।

तो, कौन सही है? जेम्स गॉस्लिंग, या नुकीला बालों वाला मालिक? आश्चर्य की बात नहीं है, गॉस्लिंग सही है। कुछ भाषाएं कुछ समस्याओं के लिए दूसरों की तुलना में बेहतर होती हैं। और आप जानते हैं, यह कुछ दिलचस्प सवाल उठाता है। जावा को C++ की तुलना में कुछ समस्याओं के लिए बेहतर डिज़ाइन किया गया था। कौन सी समस्याएं? जावा कब बेहतर है और C++ कब बेहतर है? क्या ऐसी स्थितियाँ हैं जहाँ अन्य भाषाएँ दोनों से बेहतर हैं?

जैसे ही आप इस प्रश्न पर विचार करना शुरू करते हैं, आपने असली मुसीबत खोल दी है। यदि नुकीले बालों वाले मालिक को समस्या को उसकी पूरी जटिलता में सोचना पड़ता, तो उसका दिमाग फट जाता। जब तक वह सभी भाषाओं को समतुल्य मानता है, उसे केवल वही चुनना है जो सबसे अधिक गतिमान लगती है, और चूंकि यह तकनीक की तुलना में फैशन का अधिक प्रश्न है, इसलिए वह शायद सही उत्तर भी प्राप्त कर सकता है। लेकिन अगर भाषाएं भिन्न होती हैं, तो उसे अचानक दो एक साथ समीकरणों को हल करना पड़ता है, दो चीजों के बीच एक इष्टतम संतुलन खोजने की कोशिश करनी पड़ती है जिनके बारे में वह कुछ भी नहीं जानता है: वह समस्या जिसे हल करने की आवश्यकता है, उसके लिए बीस या उससे अधिक प्रमुख भाषाओं की सापेक्ष उपयुक्तता, और प्रत्येक के लिए प्रोग्रामर, पुस्तकालय आदि खोजने की संभावना। यदि वह दरवाजे के दूसरी तरफ है, तो कोई आश्चर्य की बात नहीं है कि नुकीला बालों वाला मालिक उसे खोलना नहीं चाहता है।

यह विश्वास करने का नुकसान कि सभी प्रोग्रामिंग भाषाएं समतुल्य हैं, यह है कि यह सच नहीं है। लेकिन इसका फायदा यह है कि यह आपके जीवन को बहुत सरल बनाता है। और मुझे लगता है कि यही मुख्य कारण है कि यह विचार इतना व्यापक है। यह एक आरामदायक विचार है।

हम जानते हैं कि जावा काफी अच्छी होनी चाहिए, क्योंकि यह कूल, नई प्रोग्रामिंग भाषा है। या है? यदि आप दूर से प्रोग्रामिंग भाषाओं की दुनिया को देखते हैं, तो ऐसा लगता है कि जावा नवीनतम चीज़ है। (पर्याप्त दूर से, आप केवल सन द्वारा भुगतान किया गया बड़ा, चमकता हुआ बिलबोर्ड देख सकते हैं।) लेकिन यदि आप इस दुनिया को करीब से देखते हैं, तो आपको पता चलता है कि शीतलता की डिग्री होती है। हैकर उपसंस्कृति के भीतर, पर्ल नामक एक और भाषा है जिसे जावा से बहुत अधिक कूल माना जाता है। उदाहरण के लिए, स्लैशडॉट पर्ल द्वारा उत्पन्न होता है। मुझे नहीं लगता कि आपको वे लोग जावा सर्वर पेज का उपयोग करते हुए मिलेंगे। लेकिन एक और, नई भाषा, पायथन नामक है, जिसके उपयोगकर्ता पर्ल को नीचा दिखाते हैं, और अधिक पंखों में इंतजार कर रहे हैं।

यदि आप इन भाषाओं को क्रम में देखते हैं, जावा, पर्ल, पायथन, तो आप एक दिलचस्प पैटर्न देखते हैं। कम से कम, यदि आप एक लिस्प हैकर हैं तो आप यह पैटर्न देखते हैं। प्रत्येक लिस्प के अधिक से अधिक समान है। पायथन उन विशेषताओं की भी नकल करता है जिन्हें कई लिस्प हैकर गलतियाँ मानते हैं। आप सरल लिस्प प्रोग्रामों को लाइन दर लाइन पायथन में अनुवाद कर सकते हैं। यह 2002 है, और प्रोग्रामिंग भाषाएं लगभग 1958 तक पहुंच गई हैं।

गणित के साथ तालमेल बिठाना

मेरा मतलब है कि लिस्प को पहली बार जॉन मैकार्थी ने 1958 में खोजा था, और लोकप्रिय प्रोग्रामिंग भाषाएं अब तक केवल उन विचारों के साथ तालमेल बिठा रही हैं जिन्हें उन्होंने तब विकसित किया था।

अब, यह कैसे सच हो सकता है? क्या कंप्यूटर प्रौद्योगिकी कुछ ऐसी नहीं है जो बहुत तेज़ी से बदलती है? मेरा मतलब है, 1958 में, कंप्यूटर रेफ्रिजरेटर के आकार के विशालकाय थे जिनकी प्रसंस्करण शक्ति एक कलाई घड़ी के बराबर थी। इतनी पुरानी कोई भी तकनीक कैसे प्रासंगिक हो सकती है, नवीनतम विकास से बेहतर तो छोड़ ही दें?

मैं आपको बताता हूं कि कैसे। ऐसा इसलिए है क्योंकि लिस्प को वास्तव में एक प्रोग्रामिंग भाषा के रूप में डिज़ाइन नहीं किया गया था, कम से कम आज के अर्थ में नहीं। प्रोग्रामिंग भाषा से हमारा मतलब कुछ ऐसा है जिसका उपयोग हम कंप्यूटर को यह बताने के लिए करते हैं कि क्या करना है। मैकार्थी ने अंततः इस अर्थ में एक प्रोग्रामिंग भाषा विकसित करने का इरादा किया था, लेकिन लिस्प जो हमें वास्तव में मिला वह कुछ अलग पर आधारित था जो उसने एक सैद्धांतिक अभ्यास के रूप में किया था - ट्यूरिंग मशीन के लिए एक अधिक सुविधाजनक विकल्प को परिभाषित करने का प्रयास। जैसा कि मैकार्थी ने बाद में कहा,

यह दिखाने का एक और तरीका कि लिस्प ट्यूरिंग मशीनों से ज्यादा साफ था, एक सार्वभौमिक लिस्प फ़ंक्शन लिखना था और यह दिखाना था कि यह सार्वभौमिक ट्यूरिंग मशीन के विवरण से छोटा और अधिक बोधगम्य है। यह लिस्प फ़ंक्शन eval था..., जो लिस्प अभिव्यक्ति के मान की गणना करता है.... eval लिखने के लिए लिस्प डेटा के रूप में लिस्प फ़ंक्शन का प्रतिनिधित्व करने वाले एक संकेतन का आविष्कार करना आवश्यक था, और कागज के उद्देश्यों के लिए एक ऐसा संकेतन तैयार किया गया था, इस विचार के बिना कि इसका उपयोग व्यवहार में लिस्प प्रोग्राम व्यक्त करने के लिए किया जाएगा।

आगे क्या हुआ यह था कि, लगभग 1958 के अंत में, स्टीव रसेल, मैकार्थी के grad छात्रों में से एक ने eval की इस परिभाषा को देखा और महसूस किया कि यदि वह इसे मशीन भाषा में अनुवादित करता है, तो परिणाम लिस्प इंटरप्रेटर होगा।

यह उस समय एक बड़ा आश्चर्य था। यहाँ मैकार्थी ने बाद में एक साक्षात्कार में इसके बारे में क्या कहा:

स्टीव रसेल ने कहा, देखो, मैं इस eval को क्यों प्रोग्राम नहीं करता..., और मैंने उससे कहा, हो, हो, तुम सिद्धांत को व्यवहार से भ्रमित कर रहे हो, यह eval पढ़ने के लिए है, गणना के लिए नहीं। लेकिन उसने इसे किया। यानी, उसने मेरे पेपर में eval को [IBM] 704 मशीन कोड में संकलित किया, बग फिक्स किए, और फिर इसे लिस्प इंटरप्रेटर के रूप में विज्ञापित किया, जो यह निश्चित रूप से था। तो उस बिंदु पर लिस्प का अनिवार्य रूप से वह रूप था जो आज है....

अचानक, मुझे लगता है कि कुछ हफ्तों में, मैकार्थी ने अपने सैद्धांतिक अभ्यास को एक वास्तविक प्रोग्रामिंग भाषा में बदल दिया - और एक ऐसी भाषा जो उसने इरादा किया था उससे कहीं अधिक शक्तिशाली थी।

तो इस 1950 के दशक की भाषा के अप्रचलित न होने का संक्षिप्त स्पष्टीकरण यह है कि यह तकनीक नहीं बल्कि गणित थी, और गणित बासी नहीं होता। लिस्प की तुलना में सही चीज 1950 के दशक के हार्डवेयर से नहीं, बल्कि, मान लीजिए, Quicksort एल्गोरिथम से है, जिसे 1960 में खोजा गया था और यह अभी भी सबसे तेज सामान्य-उद्देश्यीय सॉर्ट है।

1950 के दशक से एक और भाषा अभी भी जीवित है, फोरट्रान, और यह भाषा डिजाइन के प्रति विपरीत दृष्टिकोण का प्रतिनिधित्व करती है। लिस्प सिद्धांत का एक टुकड़ा था जो अप्रत्याशित रूप से एक प्रोग्रामिंग भाषा बन गया। फोरट्रान को जानबूझकर एक प्रोग्रामिंग भाषा के रूप में विकसित किया गया था, लेकिन जिसे हम आज एक बहुत ही निम्न-स्तरीय मानेंगे।

फोरट्रान I, 1956 में विकसित भाषा, वर्तमान-दिन फोरट्रान से एक बहुत अलग जानवर थी। फोरट्रान I काफी हद तक गणित के साथ असेंबली भाषा थी। कुछ मायनों में यह अधिक हालिया असेंबली भाषाओं की तुलना में कम शक्तिशाली थी; उदाहरण के लिए, कोई सब रूटीन नहीं थे, केवल शाखाएं थीं। वर्तमान-दिन फोरट्रान अब शायद लिस्प के करीब है बजाय फोरट्रान I के।

लिस्प और फोरट्रान दो अलग-अलग विकासवादी वृक्षों के तने थे, एक गणित में और दूसरा मशीन आर्किटेक्चर में निहित था। ये दो पेड़ तब से अभिसरण कर रहे हैं। लिस्प शक्तिशाली शुरू हुआ, और अगले बीस वर्षों में तेज हो गया। तथाकथित मुख्यधारा की भाषाएं तेज शुरू हुईं, और अगले चालीस वर्षों में धीरे-धीरे अधिक शक्तिशाली हो गईं, जब तक कि अब उनमें से सबसे उन्नत लिस्प के काफी करीब नहीं हैं। करीब, लेकिन वे अभी भी कुछ चीजें गायब हैं....

लिस्प को क्या अलग बनाया

जब इसे पहली बार विकसित किया गया था, लिस्प ने नौ नए विचारों को समाहित किया। इनमें से कुछ को हम अब सामान्य मानते हैं, अन्य केवल अधिक उन्नत भाषाओं में देखे जाते हैं, और दो अभी भी लिस्प के लिए अद्वितीय हैं। मुख्यधारा द्वारा अपनाए जाने के क्रम में नौ विचार हैं,

  1. कंडीशनल्स। एक कंडीशनल एक if-then-else कंस्ट्रक्ट है। हम अब इन्हें सामान्य मानते हैं, लेकिन फोरट्रान I में वे नहीं थे। इसमें केवल एक कंडीशनल गोटो था जो अंतर्निहित मशीन निर्देश पर बारीकी से आधारित था।

  2. एक फ़ंक्शन प्रकार। लिस्प में, फ़ंक्शन डेटा प्रकार होते हैं जैसे पूर्णांक या स्ट्रिंग। उनका एक शाब्दिक प्रतिनिधित्व होता है, उन्हें चर में संग्रहीत किया जा सकता है, उन्हें तर्कों के रूप में पारित किया जा सकता है, और इसी तरह।

  3. रिकर्सन। लिस्प इसे समर्थन देने वाली पहली प्रोग्रामिंग भाषा थी।

  4. डायनामिक टाइपिंग। लिस्प में, सभी चर प्रभावी रूप से पॉइंटर्स होते हैं। मान वे होते हैं जिनके प्रकार होते हैं, चर नहीं, और चर को असाइन या बांधने का मतलब पॉइंटर्स को कॉपी करना है, न कि वे जिस ओर इशारा करते हैं।

  5. गार्बेज-कलेक्शन।

  6. अभिव्यक्तियों से बने कार्यक्रम। लिस्प कार्यक्रम अभिव्यक्तियों के पेड़ होते हैं, जिनमें से प्रत्येक एक मान लौटाता है। यह फोरट्रान और अधिकांश बाद की भाषाओं के विपरीत है, जो अभिव्यक्तियों और कथनों के बीच अंतर करते हैं।

फोरट्रान I में यह अंतर स्वाभाविक था क्योंकि आप कथनों को नेस्ट नहीं कर सकते थे। और इसलिए जब गणित के काम करने के लिए आपको अभिव्यक्तियों की आवश्यकता थी, तो किसी और चीज को मान लौटाने का कोई मतलब नहीं था, क्योंकि उसके लिए कुछ भी इंतजार नहीं कर रहा था।

ब्लॉक-स्ट्रक्चर्ड भाषाओं के आगमन के साथ यह सीमा समाप्त हो गई, लेकिन तब तक बहुत देर हो चुकी थी। अभिव्यक्तियों और कथनों के बीच का अंतर स्थापित हो गया था। यह फोरट्रान से अल्गोल और फिर दोनों के वंशजों तक फैल गया।

  1. एक प्रतीक प्रकार। प्रतीक प्रभावी रूप से हैश तालिका में संग्रहीत स्ट्रिंग्स के पॉइंटर्स होते हैं। इसलिए आप पॉइंटर की तुलना करके समानता का परीक्षण कर सकते हैं, न कि प्रत्येक वर्ण की तुलना करके।

  2. प्रतीकों और स्थिरांकों के पेड़ों का उपयोग करके कोड के लिए एक संकेतन।

  3. पूरा भाषा हमेशा मौजूद है। रीड-टाइम, कंपाइल-टाइम और रनटाइम के बीच कोई वास्तविक अंतर नहीं है। आप पढ़ते समय कोड संकलित या चला सकते हैं, संकलित करते समय कोड पढ़ या चला सकते हैं, और रनटाइम पर कोड पढ़ या संकलित कर सकते हैं।

रीड-टाइम पर कोड चलाने से उपयोगकर्ता लिस्प के सिंटैक्स को फिर से प्रोग्राम कर सकते हैं; कंपाइल-टाइम पर कोड चलाना मैक्रोज़ का आधार है; रनटाइम पर संकलित करना Emacs जैसे कार्यक्रमों में लिस्प के विस्तार भाषा के रूप में उपयोग का आधार है; और रनटाइम पर पढ़ना कार्यक्रमों को एस-एक्सप्रेशन का उपयोग करके संवाद करने में सक्षम बनाता है, एक विचार जिसे हाल ही में XML के रूप में फिर से आविष्कार किया गया है।

जब लिस्प पहली बार दिखाई दिया, तो ये विचार सामान्य प्रोग्रामिंग अभ्यास से बहुत दूर थे, जो कि 1950 के दशक के अंत में उपलब्ध हार्डवेयर द्वारा काफी हद तक निर्धारित था। समय के साथ, डिफ़ॉल्ट भाषा, लोकप्रिय भाषाओं के उत्तराधिकार में सन्निहित, धीरे-धीरे लिस्प की ओर विकसित हुई है। विचार 1-5 अब व्यापक हैं। संख्या 6 मुख्यधारा में दिखाई देने लगी है। पायथन में 7 का एक रूप है, हालांकि इसके लिए कोई सिंटैक्स नहीं लगता है।

जहां तक संख्या 8 की बात है, यह शायद सबसे दिलचस्प है। विचार 8 और 9 संयोग से लिस्प का हिस्सा बन गए, क्योंकि स्टीव रसेल ने कुछ ऐसा लागू किया था जिसे मैकार्थी ने कभी लागू करने का इरादा नहीं किया था। और फिर भी ये विचार लिस्प की अजीब उपस्थिति और इसकी सबसे विशिष्ट विशेषताओं के लिए जिम्मेदार साबित होते हैं। लिस्प अजीब दिखता है न कि इसलिए कि इसका सिंटैक्स अजीब है बल्कि इसलिए कि इसका कोई सिंटैक्स नहीं है; आप सीधे पार्स ट्री में प्रोग्राम व्यक्त करते हैं जो अन्य भाषाओं को पार्स करते समय पृष्ठभूमि में बनाए जाते हैं, और ये पेड़ सूचियों से बने होते हैं, जो लिस्प डेटा संरचनाएं हैं।

भाषा को उसके अपने डेटा संरचनाओं में व्यक्त करना एक बहुत शक्तिशाली विशेषता साबित होती है। विचार 8 और 9 एक साथ मतलब है कि आप ऐसे प्रोग्राम लिख सकते हैं जो प्रोग्राम लिखते हैं। यह एक अजीब विचार लग सकता है, लेकिन यह लिस्प में एक रोजमर्रा की बात है। इसे करने का सबसे आम तरीका कुछ ऐसा है जिसे मैक्रो कहा जाता है।