Loading...

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

Original

मई 2002

"हम C++ प्रोग्रामर्स की तलाश में थे। हम उनमें से बहुतों को लिस्प तक लाने में सफल रहे।"

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

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

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

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

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

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

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

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

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

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

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

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

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

गणित से परिचित होना

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

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

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

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

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

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

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

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

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

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

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

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

लिस्प को अलग क्या बनाता है?

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

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

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

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

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

कचरा संग्रहण।

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

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

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

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

प्रतीकों और स्थिरांकों के वृक्षों का उपयोग करके कोड के लिए एक संकेतन।

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

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

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

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

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

"मैक्रो" शब्द का लिस्प में वह अर्थ नहीं है जो अन्य भाषाओं में है। लिस्प मैक्रो किसी नई भाषा के लिए संक्षिप्त नाम से लेकर संकलक तक कुछ भी हो सकता है। यदि आप वास्तव में लिस्प को समझना चाहते हैं, या बस अपने प्रोग्रामिंग क्षितिज का विस्तार करना चाहते हैं, तो मैं मैक्रोज़ के बारे में अधिक जानना चाहूँगा।

मैक्रोज़ (लिस्प के अर्थ में) अभी भी, जहाँ तक मुझे पता है, लिस्प के लिए अद्वितीय हैं। यह आंशिक रूप से इसलिए है क्योंकि मैक्रोज़ रखने के लिए आपको संभवतः अपनी भाषा को लिस्प की तरह अजीब बनाना होगा। यह इसलिए भी हो सकता है क्योंकि यदि आप शक्ति की अंतिम वृद्धि जोड़ते हैं, तो आप अब एक नई भाषा का आविष्कार करने का दावा नहीं कर सकते, बल्कि केवल लिस्प की एक नई बोली का दावा कर सकते हैं।

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

जहाँ भाषाएँ मायने रखती हैं

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

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

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

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

केन्द्राभिमुख बल

मैं यह नहीं कह रहा हूँ कि असामान्य तकनीकों का उपयोग करने में कोई लागत नहीं आती। नुकीले बालों वाले बॉस का इस बारे में चिंता करना पूरी तरह से गलत नहीं है। लेकिन चूँकि वह जोखिमों को नहीं समझता है, इसलिए वह उन्हें बढ़ा-चढ़ाकर पेश करता है।

मैं तीन समस्याओं के बारे में सोच सकता हूँ जो कम प्रचलित भाषाओं के इस्तेमाल से उत्पन्न हो सकती हैं। हो सकता है कि आपके प्रोग्राम दूसरी भाषाओं में लिखे प्रोग्राम के साथ ठीक से काम न करें। हो सकता है कि आपके पास कम लाइब्रेरी हों। और आपको प्रोग्रामर नियुक्त करने में परेशानी हो सकती है।

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

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

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

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

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

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

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

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

औसत होने की कीमत

कम शक्तिशाली भाषा का उपयोग करने से आपको कितना नुकसान होता है? इस बारे में वास्तव में कुछ डेटा मौजूद है।

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

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

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

तो अगर आप लिस्प में लिखते हैं तो आपके प्रोग्राम कितने छोटे होंगे? उदाहरण के लिए, लिस्प बनाम सी के लिए मैंने जो संख्याएँ सुनी हैं, उनमें से अधिकांश 7-10x के आसपास रही हैं। लेकिन न्यू आर्किटेक्ट पत्रिका में ITA के बारे में हाल ही में एक लेख में कहा गया था कि "लिस्प की एक पंक्ति C की 20 पंक्तियों की जगह ले सकती है," और चूँकि यह लेख ITA के अध्यक्ष के उद्धरणों से भरा था, इसलिए मुझे लगता है कि उन्हें यह संख्या ITA से मिली है। अगर ऐसा है तो हम इस पर कुछ भरोसा कर सकते हैं; ITA के सॉफ़्टवेयर में C और C++ के साथ-साथ लिस्प भी शामिल है, इसलिए वे अनुभव से बोल रहे हैं।

मेरा अनुमान है कि ये गुणक स्थिर भी नहीं हैं। मुझे लगता है कि जब आप कठिन समस्याओं का सामना करते हैं और जब आपके पास अधिक स्मार्ट प्रोग्रामर होते हैं तो वे बढ़ जाते हैं। एक अच्छा हैकर बेहतर टूल से अधिक लाभ उठा सकता है।

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

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

इसलिए जब मैं कहता हूँ कि ITA के काल्पनिक प्रतिद्वंद्वी को कुछ ऐसा बनाने में पाँच साल लगेंगे जिसे ITA तीन महीने में Lisp में लिख सकता है, तो मेरा मतलब है कि अगर कुछ भी गलत नहीं हुआ तो पाँच साल लगेंगे। वास्तव में, जिस तरह से अधिकांश कंपनियों में काम होता है, कोई भी विकास परियोजना जिसमें पाँच साल लगते हैं, वह शायद कभी पूरी ही न हो।

मैं मानता हूँ कि यह एक चरम मामला है। ITA के हैकर असामान्य रूप से स्मार्ट लगते हैं, और C एक बहुत ही निम्न-स्तरीय भाषा है। लेकिन एक प्रतिस्पर्धी बाजार में, दो या तीन से एक का अंतर भी यह गारंटी देने के लिए पर्याप्त होगा कि आप हमेशा पीछे रहेंगे।

एक व्यंजन विधि

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

बड़े संगठनों में, इस दृष्टिकोण का वर्णन करने के लिए इस्तेमाल किया जाने वाला वाक्यांश "उद्योग का सर्वोत्तम अभ्यास" है। इसका उद्देश्य नुकीले बालों वाले बॉस को जिम्मेदारी से बचाना है: अगर वह कुछ ऐसा चुनता है जो "उद्योग का सर्वोत्तम अभ्यास" है, और कंपनी हार जाती है, तो उसे दोष नहीं दिया जा सकता। उसने नहीं चुना, उद्योग ने चुना।

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

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

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

परिशिष्ट: शक्ति

प्रोग्रामिंग भाषाओं की सापेक्ष शक्ति के बारे में मेरा क्या मतलब है, इसके उदाहरण के लिए, निम्नलिखित समस्या पर विचार करें। हम एक ऐसा फ़ंक्शन लिखना चाहते हैं जो संचायक उत्पन्न करता है - एक ऐसा फ़ंक्शन जो एक संख्या n लेता है, और एक ऐसा फ़ंक्शन लौटाता है जो एक और संख्या i लेता है और i से बढ़ा हुआ n लौटाता है।

(इसमें वृद्धि होती है, प्लस नहीं। एक संचायक को संचय करना होता है।)

कॉमन लिस्प में यह होगा

 (defun foo (n) (lambda (i) (incf ni)))

और पर्ल 5 में,

 sub foo { my ($n) = @_; sub {$n += shift} }

जिसमें लिस्प संस्करण की तुलना में अधिक तत्व हैं क्योंकि आपको पर्ल में मैन्युअल रूप से पैरामीटर निकालना पड़ता है।

स्मालटॉक में कोड लिस्प की तुलना में थोड़ा लंबा है

 foo: n |s| s := n. ^[:i| s := s+i. ]

क्योंकि यद्यपि सामान्यतः शाब्दिक चर कार्य करते हैं, आप किसी पैरामीटर को असाइनमेंट नहीं कर सकते, इसलिए आपको एक नया चर s बनाना होगा।

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

 function foo(n) { return function (i) { return n += i } }

(निष्पक्षता से कहें तो, पर्ल में भी यह अंतर बना हुआ है, लेकिन यह आपको रिटर्न्स को छोड़ने की अनुमति देकर, विशिष्ट पर्ल शैली में ही इससे निपटता है।)

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

 def foo(n): s = [n] def bar(i): s[0] += i return s[0] return bar

पायथन उपयोगकर्ता वैध रूप से पूछ सकते हैं कि वे क्यों नहीं लिख सकते

 def foo(n): return lambda i: return n += i

या और भी

 def foo(n): lambda i: n += i

और मेरा अनुमान है कि वे शायद एक दिन ऐसा करेंगे। (लेकिन अगर वे पाइथन के लिस्प में शेष विकास का इंतजार नहीं करना चाहते हैं, तो वे हमेशा ऐसा कर सकते हैं...)

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

पायथन विशेषज्ञ इस बात पर सहमत हैं कि पायथन में समस्या को हल करने के लिए यह पसंदीदा तरीका है, या तो लिखना

 def foo(n): class acc: def __init__(self, s): self.s = s def inc(self, i): self.s += i return self.s return acc(n).inc

या

 class foo: def __init__(self, n): self.n = n def __call__(self, i): self.n += i return self.n

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

पर्ल और पायथन के बीच प्रतिद्वंद्विता में, पायथन हैकर्स का दावा यह प्रतीत होता है कि पायथन, पर्ल की तुलना में अधिक सुंदर विकल्प है, लेकिन यह मामला यह दर्शाता है कि शक्ति ही परम सुंदरता है: पर्ल प्रोग्राम सरल है (इसमें कम तत्व हैं), भले ही वाक्यविन्यास थोड़ा भद्दा हो।

अन्य भाषाओं के बारे में क्या? इस वार्ता में उल्लिखित अन्य भाषाओं में - फोरट्रान, सी, सी++, जावा, और विजुअल बेसिक - यह स्पष्ट नहीं है कि आप वास्तव में इस समस्या को हल कर सकते हैं या नहीं। केन एंडरसन का कहना है कि निम्नलिखित कोड जावा में जितना संभव हो उतना करीब है:

 public interface Inttoint { public int call(int i); }

 public static Inttoint foo(final int n) { return new Inttoint() { int s = n; public int call(int i) { s = s + i; return s; }}; }

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

यह सच नहीं है कि आप इस समस्या को अन्य भाषाओं में हल नहीं कर सकते, बेशक। तथ्य यह है कि ये सभी भाषाएँ ट्यूरिंग-समतुल्य हैं, इसका मतलब है कि, सख्ती से कहें तो, आप उनमें से किसी में भी कोई भी प्रोग्राम लिख सकते हैं। तो आप यह कैसे करेंगे? सीमा मामले में, कम शक्तिशाली भाषा में लिस्प इंटरप्रेटर लिखकर।

यह एक मजाक जैसा लगता है, लेकिन बड़े प्रोग्रामिंग प्रोजेक्टों में ऐसा अक्सर होता है, इसलिए इस घटना को एक नाम दिया गया है, ग्रीनस्पन का दसवां नियम:

किसी भी पर्याप्त रूप से जटिल सी या फोरट्रान प्रोग्राम में कॉमन लिस्प के आधे भाग का अनौपचारिक रूप से निर्दिष्ट, बग-ग्रस्त धीमा कार्यान्वयन शामिल होता है।

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

यह प्रथा न केवल आम है, बल्कि संस्थागत भी है। उदाहरण के लिए, OO दुनिया में आप "पैटर्न" के बारे में बहुत कुछ सुनते हैं। मुझे आश्चर्य होता है कि क्या ये पैटर्न कभी-कभी केस (c), मानव संकलक के काम करने का सबूत नहीं होते हैं। जब मैं अपने प्रोग्राम में पैटर्न देखता हूँ, तो मैं इसे परेशानी का संकेत मानता हूँ। प्रोग्राम का आकार केवल उस समस्या को दर्शाता है जिसे हल करने की आवश्यकता है। कोड में कोई भी अन्य नियमितता एक संकेत है, कम से कम मेरे लिए, कि मैं ऐसे अमूर्तन का उपयोग कर रहा हूँ जो पर्याप्त शक्तिशाली नहीं हैं - अक्सर यह कि मैं किसी मैक्रो के विस्तार को हाथ से उत्पन्न कर रहा हूँ जिसे मुझे लिखने की आवश्यकता है।

नोट्स

आईबीएम 704 सीपीयू का आकार लगभग एक रेफ्रिजरेटर जितना था, लेकिन यह बहुत भारी था। सीपीयू का वजन 3150 पाउंड था, और 4K रैम एक अलग बॉक्स में था जिसका वजन 4000 पाउंड था। सबसे बड़े घरेलू रेफ्रिजरेटर में से एक सब-जीरो 690 का वजन 656 पाउंड है।

स्टीव रसेल ने 1962 में पहला (डिजिटल) कंप्यूटर गेम, स्पेसवार भी लिखा था।

यदि आप किसी नुकीले बालों वाले बॉस को यह विश्वास दिलाना चाहते हैं कि वह आपको लिस्प में सॉफ्टवेयर लिखने देगा, तो आप उसे बता सकते हैं कि यह XML है।

अन्य लिस्प बोलियों में संचायक जनरेटर इस प्रकार है:

 Scheme: (define (foo n) (lambda (i) (set! n (+ ni)) n)) Goo: (df foo (n) (op incf n _))) Arc: (def foo (n) [++ n _])

जेपीएल में "उद्योग की सर्वोत्तम कार्यप्रणाली" के बारे में एरान गैट की दुःख भरी कहानी ने मुझे इस सामान्यतः गलत प्रयुक्त वाक्यांश पर बात करने के लिए प्रेरित किया।

पीटर नॉरविग ने पाया कि डिज़ाइन पैटर्न में 23 में से 16 पैटर्न लिस्प में " अदृश्य या सरल " थे।

केन एंडरसन, ट्रेवर ब्लैकवेल, एरन गैट, डैन गिफिन, सारा हार्लिन, जेरेमी हिल्टन, रॉबर्ट मॉरिस, पीटर नॉरविग, गाइ स्टील और एंटोन वैन स्ट्रेटन सहित कई लोगों का धन्यवाद जिन्होंने विभिन्न भाषाओं के बारे में मेरे सवालों के जवाब दिए और/या इसके ड्राफ्ट पढ़े। व्यक्त की गई किसी भी राय के लिए वे जिम्मेदार नहीं हैं।

संबंधित:

इस वार्ता पर कई लोगों ने प्रतिक्रिया दी है, इसलिए मैंने उनके द्वारा उठाए गए मुद्दों से निपटने के लिए एक अतिरिक्त पृष्ठ बनाया है: Re: Revenge of the Nerds .

इसने LL1 मेलिंग सूची पर एक व्यापक और अक्सर उपयोगी चर्चा भी शुरू की। विशेष रूप से एंटोन वैन स्ट्रेटन द्वारा सिमेंटिक संपीड़न पर मेल देखें।

एलएल1 पर प्राप्त कुछ मेल ने मुझे भाषा शक्ति के विषय में गहराई से जाने का प्रयास करने के लिए प्रेरित किया।

संचायक जनरेटर बेंचमार्क के विहित कार्यान्वयनों का एक बड़ा सेट अपने स्वयं के पृष्ठ पर एक साथ एकत्र किया गया है।

जापानी अनुवाद ,स्पेनिश अनुवाद , चीनी अनुवाद