2 पॉइंट द्वारा GN⁺ 2026-06-12 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • 2000 के दशक से 2010 के शुरुआती वर्षों तक static typing की लोकप्रियता घटी और फिर 2010 के मध्य और उत्तरार्ध में फिर बढ़ी, इसका कारण फ़ैशन नहीं बल्कि static type systems की गुणवत्ता में सुधार था
  • जैसे गड्ढा खोदते समय कागज़ से बना फावड़ा इस्तेमाल करने से नंगे हाथ बेहतर हैं, वैसे ही खराब static type system से dynamic type system बेहतर है
  • शुरुआती Java या C++98 जैसे पुराने static type systems nullable और non-nullable का अंतर भी ठीक से नहीं कर पाते थे, उनमें sum types नहीं थे, और type names बार-बार लिखने पड़ते थे
  • TypeScript, Haskell, Swift, Rust जैसे आधुनिक type systems null का भेद, sum type/union type, और type inference को मूल रूप से उपलब्ध कराते हैं
  • IDE में method auto-completion के सामान्य हो जाने से static types में दी गई जानकारी सिर्फ error checking ही नहीं, अतिरिक्त productivity भी देती है

static typing की लोकप्रियता में बदलाव पर एक परिकल्पना

  • 2000 के दशक से 2010 के शुरुआती वर्षों में static typing की लोकप्रियता घटी और फिर 2010 के मध्य और उत्तरार्ध में बढ़ी, इसका कारण
    यह नहीं था कि programming एक trend-driven industry है, बल्कि यह था कि व्यापक रूप से इस्तेमाल होने वाले static type systems की गुणवत्ता बेहतर हुई

फावड़ा उपमा — टूल की गुणवत्ता ही चुनाव तय करती है

  • गड्ढा खोदते समय अगर फावड़ा उपयोगी हो तो स्वाभाविक है कि नंगे हाथों की बजाय फावड़ा इस्तेमाल किया जाएगा,
    लेकिन अगर उपलब्ध एकमात्र फावड़ा कागज़ का बना हो, तो वह सिर्फ मिट्टी को बेकार में उलट-पुलट करेगा और ऐसे में नंगे हाथ बेहतर हैं
  • dynamic type systems में variables और fields की स्थिति व सामग्री को पूरी तरह अपने दिमाग से ट्रैक करना पड़ता है,
    कंप्यूटर न मदद करता है न बाधा, इसलिए यह नंगे हाथों से खोदने जैसा है
  • 1990 के दशक और 2000 के शुरुआती वर्षों में आम रहे कमजोर static type systems कागज़ के फावड़े जैसे थे
    • वे nullable और non-nullable pointers में अंतर जैसी साधारण चीज़ में भी मदद नहीं कर पाते थे
    • उनमें सिर्फ product types थे, sum types नहीं थे
    • type names को जगह-जगह हाथ से लिखने का बोझ था
    • BufferedReader bufferedReader = new BufferedReader(new FileReader(filename)); जैसा code एक छोटा disaster है

आधुनिक type systems हमेशा क्या उपलब्ध कराते हैं

  • TypeScript, Haskell, MyPy, Swift, Rust जैसे आधुनिक type systems की तुलना में, ये हमेशा नीचे की चीज़ें देते हैं
  • nullable और non-nullable का भेद

    • Haskell Maybe t, TypeScript T | null, Swift T?, Rust Optional<T> देता है
    • type system आसानी से उन सभी स्थानों और उनकी कमी को दिखा देता है जहाँ null check की ज़रूरत है
    • व्यवहार में runtime पर null pointer errors लगभग देखने को नहीं मिलते
  • sum type या union type

    • यह "गलत states को अभिव्यक्त करना असंभव बनाना (Make invalid states unrepresentable)" जैसी practice को संभव बनाता है
    • कई fields वाले state machine objects बनाए जा सकते हैं, और हर field सिर्फ उसी state में मौजूद होती है जहाँ वह प्रासंगिक हो
  • type inference

    • compiler let x = 5; को number समझ सकता है, इसलिए let x: number = 5; लिखने की ज़रूरत नहीं होती

IDE features के प्रसार से बढ़ी उपयोगिता

  • method name auto-completion जैसे IDE features के सामान्य होने से static type systems की उपयोगिता बढ़ी
    • 1990 के दशक में Visual Studio का Intellisense एक killer feature था, लेकिन 2020 के दशक में लगभग हर IDE और editor में ऐसे features उपलब्ध हैं
    • static type systems में दी गई जानकारी error checking के अलावा अतिरिक्त productivity लाभ भी देती है

निष्कर्ष

  • अच्छा dynamic type system, खराब static type system से बेहतर है
  • लेकिन अब हमारे पास अतीत की तुलना में कहीं बेहतर static type systems हैं

1 टिप्पणियां

 
GN⁺ 2026-06-12
Lobste.rs की रायें
  • यह लेख अच्छा है, लेकिन मैं इससे पूरी तरह सहमत नहीं हूँ। 2000 के दशक की शुरुआत के static type systems भले शानदार नहीं थे, फिर भी वे बिल्कुल static typing न होने से कहीं बेहतर थे
    closed sum types नहीं थे, लेकिन subtyping से काफी हद तक उसे model किया जा सकता था, और non-nullable types नहीं थे, लेकिन C++ के references और non-pointer types, तथा Java के primitive types कुछ हद तक यह काम कर लेते थे। Ruby या JavaScript में न सिर्फ हर type nullable था, बल्कि उसे string की तरह, integer की तरह, और प्रोग्राम के हर दूसरे type की तरह भी treat किया जा सकता था, इसलिए स्थिति और खराब थी
    मेरा मानना है कि static typing के पक्ष में रुख बदलने का बड़ा कारण Web 2.0 social network boom के दौरान यह था कि first-mover advantage हर चीज़ से ज़्यादा महत्वपूर्ण था। Ruby या Python में technical debt इकट्ठा करते हुए भी जल्दी launch करना और iterate करना, Friendster या Digg की तरह पीछे छूट जाने से बेहतर था, और अगर performance धीमी हो तो उस समय आसानी से मिलने वाली low-interest capital से बस और server खरीद लिए जाते थे
    बाद के mobile boom में software को सीमित और हमारे नियंत्रण से बाहर user devices पर चलना पड़ा, और धीमे dynamic type apps सचमुच धीमे थे, साथ ही type error आने पर server की तरह top-level response handler में gracefully recover भी नहीं किया जा सकता था। उस माहौल में static typing की safety और performance कहीं अधिक असरदार लगने लगी

    • Java और 90s-शैली के C++ को dynamic typed language codebases से तुलना करके bug rate समान होने की बात करने वाले कई papers हैं, और dynamic language के समर्थक अक्सर इन्हें static typing के बेकार होने के सबूत की तरह पेश करते हैं
      2000 के दशक की शुरुआत में मैं भी इससे सहमत था, क्योंकि उस समय के type systems अक्सर लगभग कभी गलत न होने वाले गुणों को ही enforce करते थे, जबकि code को structure करने में मदद न देने वाली पाबंदियाँ लगा देते थे। खासकर subtyping और implementation inheritance का मिला-जुला तरीका लचीला नहीं था
      ज़्यादा modern type systems इस्तेमाल करने के बाद मेरी राय बदल गई। snmalloc में C++ type system से memory ownership state machine enforce की जाती है, और दूसरे codebases में ring buffer counters के सही overflow behavior की जाँच की जाती है। दोनों ही चीज़ें गलत हों तो debug करना झंझट भरा होता है और आम error source भी होती हैं, लेकिन compiler ने ऐसे code पर fail कराया जिसे मैं सही समझ रहा था, और इस तरह bug को tree में जाने से रोक दिया
    • मेरा मानना है कि dynamic typed language में development करना static typed language की तुलना में धीमा होता है। इसका उलटा दावा मैं बार-बार देखता हूँ, लेकिन समझ नहीं आता
      IDE में . दबाकर method name के कुछ अक्षर टाइप करना और सही candidate पर Enter दबा देना, हर कुछ सेकंड में 2 सेकंड बचाता है, और जब यह न पता हो कि कौन-सा method मौजूद है, तब class definition खोजने में लगने वाले 30 सेकंड भी बचते हैं। यह बात https://grugbrain.dev/#grug-on-type-systems में भी अच्छी तरह दर्ज है
      function parameter types लिखने की तुलना में method call करने वाली code lines हम कहीं ज़्यादा बार लिखते हैं, इसलिए यह सौदा dynamic typing के बहुत ख़िलाफ़ जाता है। असली मूल्य runtime पर fail होने वाला बेतुका code अनुमति देने में नहीं था, बल्कि local variable types को omit करने में था, और static typed languages को शुरू से ही उसे मना करने की ज़रूरत नहीं थी
    • 2000 के दशक की शुरुआत के लोकप्रिय type systems सिर्फ “बहुत अच्छे नहीं थे” भर नहीं थे, वे वाकई खराब थे, और बहुत verbose भी थे
      जो दुर्लभ codebases type system का गंभीरता से उपयोग करते थे, उनमें कई पन्नों तक ऐसा code भरा रहता था जो कुछ कहता ही नहीं था, फिर भी runtime conditionals का ढेर लगा रहता था, और Java में type hierarchy बढ़ने के साथ program भी वास्तव में धीमा हो जाता था। ज़्यादातर codebases type का छिटपुट उपयोग करते थे और runtime conditionals बहुत रखते थे, इसलिए आवश्यक test coverage के मामले में dynamic type systems की तुलना में बहुत कम बचत होती थी
      dynamic typed languages में static rewards नहीं थे, लेकिन वे concise थीं, इसलिए पढ़ना और review करना आसान था, और testing भी आसान थी। खासकर late 90s से early 2000s के dependency injection frameworks जैसे माहौल में, जहाँ हर नई service जोड़ने पर कई XML files बदलनी पड़ती थीं, यह और भी सच था। RAM का आधा हिस्सा खा जाने वाले IDE के बिना भी काम किया जा सकता था
      मेरे शुरुआती करियर का अनुभव बिल्कुल ऐसा ही था, इसलिए मैं इस लेख से पूरी तरह सहमत हूँ। Java 1.4 से Java 6 तक cost-benefit इतना खराब था कि मैं static typed languages को लगभग छोड़ ही बैठा था, और कुछ साल बाद शौक़िया तौर पर Haskell आज़माने के बाद ही समझ पाया कि static typing का cost-benefit वाजिब भी हो सकता है, समस्या Java थी। “python is not java” निबंध भी उस अंधेरे दौर को अच्छी तरह दिखाता है
    • inheritance-based subtyping और भी कमज़ोर था। उसमें exhaustiveness checking वाले pattern matching जैसी उपयोगिता नहीं मिलती थी, और implementation कई जगहों में बँट जाती थी
    • प्रतियोगियों से पहले site लॉन्च करके उसे users के सामने लाना और scale economies को lock-in कर लेना महत्वपूर्ण था — यह व्याख्या आज की स्थिति से भी काफ़ी परिचित लगती है
  • यह सवाल है कि static typing युग की मुख्यधारा बनने के बाद क्या हमने अपने software में reliability का फायदा वास्तव में देखा भी है
    मुझे लगा था कि static typing का फायदा ज़्यादा immediate development feedback और गंभीर runtime failure को कम करने में है, लेकिन सैद्धांतिक रूप से ऐसे failure हमेशा संभव होने पर भी व्यवहार में वे इतने बार होते नहीं लगे

    • देखा है। जैसे ही हमने किसी गैर-तुच्छ TypeScript codebase में TypeScript error 0 रखने को लक्ष्य बनाया, undefined और null पर method call करने की कोशिशें तेज़ी से कम हो गईं
      junior और कुछ senior शुरू में सशंकित थे कि जगह-जगह @ts-ignore भर जाएगा, लेकिन वास्तव में ऐसे लगभग तीन ही मामले थे, जिनमें dependencies के टूटे हुए type भी शामिल थे। पहले development branch में type confusion की वजह से हफ्ते में लगभग एक बार app crash हो जाता था और मेरा काम रुक जाता था, लेकिन अब आख़िरी बार ऐसा कब हुआ था, यह भी याद नहीं
      सिर्फ tsc को संतुष्ट करने से भी type-related bug कम हुए, यहाँ तक कि उन हिस्सों में भी जहाँ code मैंने खुद नहीं लिखा था। दूसरी ओर आजकल linter बहुत ज़्यादा उत्साही हो गए हैं, और Sonar जैसे tools को संतुष्ट करने की कोशिश में मैंने असली refactoring breakage देखी है। 95% warning झूठी थीं, 3% tool की bug थीं, और जो 2% मददगार थीं वे भी असली bug का कारण नहीं थीं। codebase को उनके हिसाब से ढालने में 1 हफ्ता लगाने पर एक bug पकड़ा, लेकिन उसी प्रक्रिया में दो और डाल दिए
      tsc को संतुष्ट करने वाले काम से मोटे तौर पर रोज़ 2 शुद्ध bug fix और 1 regression निकलती थी, लेकिन regression आम तौर पर पूरे crash की बजाय गलत behavior जैसी कम गंभीर चीज़ होती थी
      इसमें property-based testing जोड़ने पर औसतन 2~4 घंटे लगते थे और हर बार कम-से-कम एक bug सामने आता था। अगर code को property-based testing के लिए तैयार किया जा सकता है, तो यह करना चाहिए
      DeepSeek V4 Flash जैसे सस्ते model से test coverage बढ़ाई, लेकिन इस बात का ध्यान रखा कि बेकार test न बनें; इससे रोज़ लगभग 2~3 logic bug ठीक हुए और crash नहीं हुए। हालांकि test suite बस किसी तरह maintainable स्तर पर है
      जब junior को Sonnet और Opus 4.5, 4.6 सीरीज़ से मोटे तौर पर test बनवाने दिए, तो models ने सिर्फ ऐसे test बनाए जो “मौजूदा behavior को document” करते थे, इसलिए सुधार का असर कम था, और test suite maintain न हो पाने लायक थी, इसलिए उसे फेंकना पड़ा
      model-based testing bug पकड़ने में बहुत अच्छी है, लेकिन इसकी setup जटिल है, और models को सतही features पर cycles बर्बाद किए बिना कोने-कोने में घुसने के लिए प्रेरित करना बहुत झंझट भरा है। profile-based model-based fuzzer जैसा कुछ हो तो दिलचस्प होगा
      संक्षेप में, type checker गंभीर failure और कई तरह की confusion को अच्छी तरह पकड़ते हैं, और property-based testing शानदार है। सामान्य testing में लगातार लाभ पाने के लिए बहुत अनुशासन चाहिए
    • मेरे व्यक्तिगत अनुभव में हाँ। मैं जो JavaScript इस्तेमाल करता हूँ उसमें null pointer bug TypeScript पर जाने के बाद लगभग नगण्य हो गए, और मेरे सहकर्मियों का अनुभव भी ऐसा ही था
  • यहाँ TypeScript को अच्छे type system के साथ एक ही श्रेणी में रखना सबसे कम स्वीकार्य लगता है

    • सही है। TypeScript sound नहीं है, और खासकर await के पार type narrowing जिस तरह काम करती है, उसने मुझे कई बार काटा है। फिर भी इसने स्थिति को नाटकीय रूप से बेहतर किया है
      सच कहूँ तो structural typing को भी मैंने आख़िरकार स्वीकार कर लिया, और मुझे लगता है कि इसका आगे की language design पर सकारात्मक असर होगा
  • यह दावा बहुत कमज़ोर है। algebraic data type और type inference वाले ठीक-ठाक programming language 90 के दशक के मध्य से मौजूद थे
    Java और C++ के type system बहुत कमज़ोर थे, लेकिन SML, OCaml, Haskell पहले से थे और उनका अनुभव आज से बहुत अलग नहीं था। अगर लोगों ने उन भाषाओं का इस्तेमाल नहीं किया, तो वह culture, adoption और उन आवश्यकताओं का सवाल है जो शब्दों में सामने नहीं आईं; इसे सिर्फ इस तरह नहीं समझाया जा सकता कि “उपयोगी type system काफ़ी अच्छे नहीं थे”
    या अगर दावा यह है कि “तब की लोकप्रिय भाषाओं के type system खराब थे, और आज की लोकप्रिय भाषाओं के type system बेहतर हैं, इसलिए type system ज़्यादा लोकप्रिय हो गए”, तो यह circular logic जैसा लगता है
    उन भाषाओं में भी बहुत बारीकी है जो type system के साथ डिज़ाइन हुईं, और उन भाषाओं में भी जो मूल रूप से बिना type के डिज़ाइन हुईं और बाद में उन पर type system चढ़ाया गया

  • जो व्यक्ति मूल रूप से dynamic typing को पसंद करता रहा है, उसकी नज़र से भी यह लेख काफ़ी संतुलित लगता है। आजकल मैं C# में काम करता हूँ, शौक़ में Lisp इस्तेमाल करता हूँ, और पहले Python भी इस्तेमाल करता था
    जब मुझे Java 5 इस्तेमाल करनी पड़ती थी, तो ज़्यादातर library developer के ख़राब फ़ैसलों की वजह से type system से लगातार लड़ना पड़ता था। 2010 के आसपास C# पर आने के बाद type system सक्रिय रूप से हानिकारक तो नहीं था, लेकिन ज़्यादातर दोहराव-भरा था, और Python में सबसे आम type confusion यानी null pointer exception को भी नहीं रोक पाता था
    C# का type system वास्तव में 2020 के आसपास मददगार बनना शुरू हुआ, जब non-nullable reference type आए। इस साल native union type भी आएँगे, लेकिन exhaustiveness लागू करने वाली union type library कम-से-कम 2016 से संभव थीं और मैं उन्हें 2020 से इस्तेमाल कर रहा हूँ
    मुझे अब भी लगता है कि trend की भूमिका है, लेकिन उसका कुछ हिस्सा बुरा नहीं है। ज़्यादा expressive type system वाली trendy भाषाओं ने उन साधारण भाषाओं में भी सुधार लाया है जिन्हें हम पैसे लेकर काम में इस्तेमाल करते हैं

  • Haskell और उसका type system 2000 के दशक में भी पहले से मौजूद था। आज जितना व्यापक रूप से इस्तेमाल नहीं होता था, लेकिन वह निश्चित रूप से मौजूद था, इसलिए इस दावे में उस हिस्से को और बेहतर तरीके से शामिल किया जाना चाहिए
    मेरी निजी राय में, TypeScript मुख्यधारा की languages इस्तेमाल करने वाले users को बेहतर type system से परिचित कराने वाला एक बड़ा कारण था। quality और Microsoft के support के अलावा, इसका फ़ायदा यह भी था कि यह JavaScript पर लागू होता था, और JavaScript को Python की तुलना में types की ज़रूरत ज़्यादा थी। इसकी वजह “Undefined is not a function.” और “The good parts.” थे

    • अच्छा होगा अगर JavaScript के नवीनतम संस्करणों के हिसाब से “good parts” किताब अपनी संक्षिप्तता बनाए रखते हुए फिर से आए
      “Real World Haskell” 2008 में आई थी, और उसका लक्ष्य मुख्यधारा के programmers के लिए Haskell को अधिक आकर्षक बनाना था। अच्छी ख़बर फैलाने में उसने कितना योगदान दिया, यह मुझे नहीं पता
      Java दुनिया में Scala 2004 में शानदार types लेकर आया था, और .NET में F# 2005 में आया। Scala ने शायद Twitter जैसे सबसे नज़र आने वाले users हासिल किए, लेकिन TypeScript की तरह वह उस platform के users के बड़े हिस्से को अपने भीतर समाहित करने की स्थिति में नहीं था, और न ही Rust या Go की तरह दूसरे language users को बड़ी संख्या में खींच लाने जितना आकर्षक था
    • लेख इस मुद्दे को पहले ही कवर करता है। 90 के दशक और 2000 के शुरुआती दौर के लोकप्रिय शुरुआती Java या C++98 जैसे कमज़ोर static type systems की तुलना कागज़ के फावड़े से की गई थी
      ठीक अगले paragraph में Haskell को “modern type system” कहा गया है, लेकिन 90 के दशक के अंत और 2000 के शुरुआती दौर में Haskell का अनुभव रखने वाले लोग, सिर्फ़ व्यक्तिगत स्तर पर थोड़ा बहुत छूकर देखने वालों को भी शामिल करें तो, व्यावहारिक रूप से 0% के करीब थे। लेख यह बता रहा है कि उस समय ज़्यादातर developers ने static typed languages को कैसे अनुभव किया, और क्यों उस बहुसंख्यक समूह ने सामूहिक रूप से static typed languages से दूरी बनाई
    • मेरा मानना है कि Haskell और OCaml कुछ हद तक tool ecosystem की कमज़ोरी से जूझते हैं। language ख़ुद शानदार हैं, लेकिन tooling की तरफ़ से होने वाली अनगिनत छोटी-छोटी paper cuts की वजह से adoption खो देते हैं
      उदाहरण के लिए, OCaml में dune इस्तेमाल करने के लिए आपको opam file, dune file, ocaml module syntax, और ocaml syntax समझना पड़ता है। Haskell के optional compiler extensions भी उतने ही डरावने लगते हैं
      इसके उलट, cargo में आपको सिर्फ़ toml और Rust जानना होता है