17 पॉइंट द्वारा GN⁺ 2025-07-26 | 8 टिप्पणियां | WhatsApp पर शेयर करें
  • प्रोग्रामिंग में type system का उपयोग करके अलग-अलग डेटा अर्थों को स्पष्ट रूप से अलग किया जा सकता है
  • string या integer जैसे सामान्य types को ज्यों का त्यों इस्तेमाल करना संदर्भ खो देता है और bug का कारण बन सकता है
  • आधार type एक ही हो, तब भी उद्देश्य के अनुसार नया type define करने पर compile time errors के जरिए गलतियों को रोका जा सकता है
  • Go library libwx में measurement units को साफ़ तौर पर अलग करने वाले types define किए गए हैं, जिससे float64 के मिश्रित उपयोग से होने वाली गलतियों को रोका जा सके
  • उदाहरण code में UUID type को UserID और AccountID में अलग किया गया है ताकि गलत उपयोग को compiler रोक दे
  • Go जैसी अपेक्षाकृत कम सख्त type system वाली भाषाओं में भी सरल type wrapping से bug रोके जा सकते हैं

type system का सक्रिय रूप से उपयोग करें

समस्या की शुरुआत: साधारण types का मिलाजुला उपयोग

  • प्रोग्रामिंग में string, int, UUID जैसे मूल types से बहुत-सी values को व्यक्त किया जाता है
  • लेकिन जैसे-जैसे प्रोजेक्ट बड़ा होता है, इन साधारण types का बिना भेदभाव के आपस में मिलकर इस्तेमाल होने की गलती अक्सर होने लगती है
    • उदाहरण: userID string को गलती से accountID के रूप में पास कर देना, या int arguments 3 वाले function में क्रम गलत दे देना

समाधान: इरादा स्पष्ट करने वाले type definitions

  • int या string केवल building blocks हैं; इन्हें पूरे system में ज्यों का त्यों पास करने से अर्थपूर्ण संदर्भ खो जाता है
  • इसे रोकने के लिए हर भूमिका के लिए अलग type define करके उसका उपयोग करना चाहिए
    • उदाहरण:
      type AccountID uuid.UUID  
      type UserID uuid.UUID  
      
      func UUIDTypeMixup() {  
          {  
              userID := UserID(uuid.New())  
              DeleteUser(userID)  
              // 에러 없음  
          }  
      
          {  
              accountID := AccountID(uuid.New())  
              DeleteUser(accountID)  
              // 에러: AccountID 타입을 UserID로 사용할 수 없음  
          }  
      
          {  
              accountID := uuid.New()  
              DeleteUserUntyped(accountID)  
              // 컴파일 타임 에러 없음, 런타임에 문제가 발생할 가능성 높음  
          }  
      }  
      
  • इससे गलत type वाले arguments को compile time पर रोका जा सकता है

वास्तविक उपयोग का उदाहरण: libwx library

  • लेखक अपनी Go library libwx में इस तकनीक का उपयोग कर रहे हैं
  • हर measurement unit के लिए dedicated type define किया गया है, और unit conversion methods भी type से जोड़ी गई हैं
    • उदाहरण: Km.Miles() method के जरिए units को स्पष्ट रूप से अलग रखा जाता है
  • नीचे गलत function argument order और unit confusion को compiler द्वारा रोके जाने का उदाहरण है:
    // 화씨 온도 선언  
    temp := libwx.TempF(84)  
    
    // 상대습도 선언(퍼센트)  
    humidity := libwx.RelHumidity(67)  
    
    // 화씨 대신 섭씨 온도를 요구하는 함수에 잘못 전달  
    fmt.Printf("Dew point: %.1fºF\n",  
      libwx.DewPointC(temp, humidity))  
    // 컴파일러가 타입 mismatch 오류를 바로 검출  
    // temp (TempF 타입)는 TempC로 사용할 수 없음  
    
    // 함수에 인자 순서 잘못 전달  
    fmt.Printf("Dew point: %.1fºF\n",  
      libwx.DewPointF(humidity, temp))  
    // 컴파일러가 인자 타입 오류를 막아줌  
    
  • अगर केवल float64 का उपयोग किया जाता, तो होने वाली ऐसी गलतियों को पूरी तरह रोका जा सकता है

निष्कर्ष: type system का सक्रिय रूप से उपयोग करें

  • type system केवल syntax जाँचने का साधन नहीं, बल्कि bug रोकने का tool है
  • हर model के लिए ID type अलग define करना चाहिए, और function arguments को भी float या int की जगह स्पष्ट types में wrap करना चाहिए
  • यह तरीका Go जैसी कम सख्त type system वाली भाषाओं में भी बेहद प्रभावी है और लागू करना आसान है
  • व्यवहारिक दुनिया में UUID या string types के मिलेजुले उपयोग से होने वाले bugs वाकई बहुत आम हैं
  • लेखक इस बात पर ज़ोर देते हैं कि इतना सरल तरीका production code में आम तौर पर उपयोग नहीं किया जाता, यह आश्चर्यजनक है

संबंधित code

8 टिप्पणियां

 
vk8520 2025-07-29

जहाँ तक मुझे पता है, Kotlin में इसका इस्तेमाल करने पर primitive को wrapper में लपेटना पड़ सकता है, जिससे वह stack की बजाय heap में store होता है और performance issue हो सकता है। बेशक, ज़्यादातर use case में maintainability को प्राथमिकता दी जाती है। साथ ही, value class का उपयोग करके performance समस्या को न्यूनतम किया जा सकता है।

 
regentag 2025-07-28

Ada भाषा में इस मामले में वाकई एक बेहतरीन type system है। अलग-अलग तरह के मानों को आसानी से अलग type के रूप में घोषित किया जा सकता है, और अगर वे मिल जाएँ तो compiler उसे अच्छी तरह पकड़ लेता है।

 
roxie 2025-07-28

जिज्ञासा से पूछ रहा/रही हूँ। क्या दूसरे लोकप्रिय type languages की तुलना में इसके कुछ अलग फायदे भी हैं? (kotlin, rust, typescript, ...)

 
regentag 2025-07-28

Ada का फ़ायदा ज़्यादातर "C से बेहतर है" वाली तरफ़ है। C में डेवलपर पर भरोसा करके काफ़ी ऐसी चीज़ों की अनुमति होती है जिन्हें सीमित किया जाना चाहिए। जैसे implicit type conversion वगैरह। लेकिन ज़्यादातर डेवलपर्स शायद आदत की वजह से C को ज़्यादा पसंद करते हैं...

हो सकता है यह उस codebase की विशेषता हो जिस पर मैं काम करता हूँ, लेकिन हम लगभग हर चीज़ को अलग type के रूप में घोषित करके इस्तेमाल करते हैं। basic type का इस्तेमाल तो बस array index जैसी चीज़ों में ही होता है।

 
roxie 2025-07-28

समझ गया, धन्यवाद

 
GN⁺ 2025-07-26
Hacker News राय
  • मुझे यह तरीका पसंद है, यानी 'खराब state को represent ही न किया जा सके(make bad state unrepresentable)' वाला तरीका, लेकिन इस पैटर्न में आम समस्या यह होती है कि डेवलपर्स type implementation के सिर्फ पहले चरण पर ही रुक जाते हैं, सब कुछ type बन जाता है और वे एक-दूसरे के साथ अच्छी तरह compatible नहीं रहते, बहुत सारे हल्के-फुल्के बदले हुए type बन जाते हैं जिससे code को trace करना और समझना मुश्किल हो जाता है, ऐसी स्थिति में मैं तो बेहतर समझूँगा कि इसे weakly typed dynamic language (JS) या strongly typed dynamic language (Elixir) में लिखा जाए, लेकिन अगर डेवलपर्स conditional logic को pattern matching वाले union types में धकेलते रहें, delegation का अच्छा इस्तेमाल करें, और type-driven flow को आगे बढ़ाते रहें, तो development experience फिर से सुखद हो जाता है, उदाहरण के लिए 'DewPoint' function कई types लेकर भी स्वाभाविक रूप से काम कर सकता है

    • इसी वजह से, मैं चाहता हूँ कि और भाषाएँ bounded (Integer range-limited) types को built-in support दें, जैसे x: u32 के बजाय type system यह enforce कर सके कि x सिर्फ [0,10) range में ही हो, इससे array indexing में bounds check की ज़रूरत नहीं रहेगी, Option जैसी चीज़ों के लिए peephole optimization भी बहुत आसान हो जाएगी, Rust में function के अंदर कुछ हद तक LLVM की वजह से ऐसा support मिलता है, लेकिन functions के बीच variables पास करते समय नहीं

    • जानकारी के लिए, Ruby weakly typed नहीं बल्कि strongly typed है, 1 + "1" जैसा operation करने पर 'TypeError: String can't be coerced into Integer' जैसी error आती है

    • 'type implementation के पहले चरण पर रुक जाना' ही failure का कारण है, उदाहरण के लिए int को struct में wrap करके UUID की तरह इस्तेमाल करना एक अच्छी शुरुआत है, लेकिन अगर किसी के पास सिर्फ int हो और वह उसे type wrap करके पास कर दे, तो वह UUID की वह property तोड़ सकता है कि वह वास्तव में unique होना चाहिए, आखिरकार 'Correct by construction(निर्माण के समय ही सही होने की गारंटी)' महत्वपूर्ण है, UUID जैसे uniquely constrained types को तब तक बनाया ही न जा सके जब तक किसी function या constructor में exception फेंककर या किसी और तरीके से वास्तव में यह साबित न किया जाए, यह विचार सिर्फ UUID पर नहीं बल्कि किसी भी type और invariant पर लागू हो सकता है

    • हाल ही में मैं Red-Green-Refactor pattern का पालन कर रहा हूँ, लेकिन failing tests के बजाय type system को और कड़ा बना देता हूँ ताकि bugs type checker में पकड़े जाएँ, नई features, edge cases, या वे bugs जिन्हें type से induce नहीं किया जा सकता, उन्हें मैं अभी भी tests से संभालता हूँ, लेकिन type system का उपयोग करने वाला red-green-refactor आम तौर पर तेज़ होता है और bugs की एक बड़ी category को पूरी तरह रोक सकता है

    • structural types से ज़्यादातर समस्याओं को कम किया जा सकता है, और जब सच में ज़रूरत हो तभी nominal types से enforce किया जा सकता है

  • exceptions और types से जुड़े मुद्दे की बात करें तो, मुझे लगता है कि checked exceptions का अच्छा उपयोग करके type के अनुसार उन्हें ठीक से handle करना अच्छा है, मुझे समझ नहीं आता कि Java के checked exceptions की इतनी आलोचना क्यों होती है, जिन projects पर मैंने काम किया वहाँ जब हमने checked exceptions का उपयोग अनिवार्य किया तो शुरू में सबको नापसंद था, लेकिन code flow के हर exceptional case के बारे में सोचने की आदत पड़ने के बाद सबको यह पसंद आने लगा, unit tests के मामले में हम इतने सख्त नहीं थे, लेकिन project बहुत robust हो गया

    • Java checked exceptions को लेकर शिकायत यह है कि exception handling बहुत झंझट भरी है, library author checked exceptions को साफ़-साफ़ तय नहीं कर पाता, और client side पर हर बार function call करते समय बेकार की exception handling लिखनी पड़ती है, इसलिए लोग इससे चिढ़ जाते हैं, अगर exceptions को आसानी से दूसरे type में या runtime exception में बदला जा सकता, या module/app स्तर पर सिर्फ declare करना काफी होता, तो यह समस्या कम होती, लेकिन अभी यह बहुत बोझिल है, और signatures आसानी से टूट जाते हैं, इसलिए domain-specific exceptions का उपयोग करना चाहिए, लेकिन Java exception translation को भी असुविधाजनक बना देता है, checked exceptions अच्छे हैं लेकिन Java की exception ergonomics पसंद नहीं

    • checked exceptions की आलोचना उनकी overuse की वजह से हुई, Java का checked और unchecked दोनों को support करना एक अच्छा निर्णय है, लेकिन Eric Lippert के कहे 'exogenous' exceptions जैसी चीज़ों में ही checked exceptions का उपयोग करना चाहिए और बाकी ज़्यादातर को unchecked में बदल देना चाहिए, उदाहरण के लिए DB का connection कभी भी टूट सकता है, लेकिन 'throws SQLException' को call stack में ऊपर तक ढोते रहना बहुत झंझट है, top level पर catch-all करके HTTP 500 लौटाना काफी है, संबंधित लेख

    • checked exceptions (unchecked की तुलना में) में अगर call stack की गहराई में कोई function अब exception फेंकने लगे, तो सिर्फ handling function ही नहीं बल्कि बीच के सारे functions भी बदलने पड़ सकते हैं, यानी system बदलने पर flexibility कम हो जाती है, async function coloring वाला विवाद भी कुछ ऐसा ही है, अगर कोई function exception फेंक सकता है, तो या तो उसे try/catch में wrap करो, या caller भी declare करे कि वह exception फेंकता है

    • C# में types स्पष्ट हैं लेकिन unchecked exceptions अपनाए गए हैं, error stack साफ़-सुथरा रहता है और कोई समस्या नहीं होती, pattern-matched exception handlers के हर level पर bespoke handling करने से यह अधिक साफ़ लगता है, अगर robust unwrapped error results हों तो मुझे यह काफ़ी समान लगता है

    • Java में checked types की usability कम है, उदाहरण के लिए stream API इस्तेमाल करते समय अगर map/filter function checked exception फेंके तो स्थिति बहुत कठिन हो जाती है, और अगर कई services calls में हर एक की अपनी checked exception हो, तो अंततः या तो Exception पकड़ना पड़ता है या बेहिसाब लंबी exception list लिखनी पड़ती है

  • कुल मिलाकर मैं 'distinct types बनाओ' वाली नीति से सहमत हूँ, लेकिन ऐसे systems में काम करना मुश्किल लगा है जहाँ हर चीज़ का अलग type हो, खासकर जब सिर्फ bytes इधर-उधर ले जाने वाला code और domain computation वाला code एक साथ मिला हो

    • वह एहसास समझ सकता हूँ, data पहले से मौजूद है, लेकिन पहले type बनाना या instance create करना कैसे है यह खोजना पड़ता है, recipe न हो तो ऐसा लगता है जैसे documentation से लड़ रहे हों, जैसे {x, y, z} object है, लेकिन पहले createVector(x, y, z): Vector function इस्तेमाल करना पड़े, और Face बनाने के लिए createFace(vertices: Vector[]): Face जैसा कुछ करना पड़े, तो प्रक्रिया बेवजह लंबी लगती है, BouncyCastle जैसी जगहों पर byte arrays तैयार होने के बाद भी कई types बनाने और उनके methods इस्तेमाल करने पड़ते हैं तब जाकर असली काम हो पाता है

    • Go भाषा में type alias को मूल type (जैसे AccountID → int) में वापस बदलना काफ़ी आसान है, सही structure हो तो domain logic में type alias इस्तेमाल करें, और domain की परवाह न करने वाली libraries की तरफ higher/lower types में convert करके clean architecture style अपनाई जा सकती है, लेकिन conversion code बहुत ज़्यादा लिखना पड़ता है

    • Phantom types ऐसे मामलों में उपयोगी होते हैं, type parameter (यानी generics) जोड़ते हैं लेकिन वास्तव में उस parameter का कहीं उपयोग नहीं होता, मैंने पहले Scala में crypto code लिखते समय इसका उपयोग किया था, arrays सब bytes ही थे लेकिन phantom types से उन्हें आपस में mix होने से रोका, संबंधित उदाहरण

    • आदर्श रूप में compiler सिर्फ types verify करे और फिर बाकी सारा domain logic साधारण byte copy में lower कर दे, हालांकि पता नहीं मैं तुम्हारा मतलब ठीक से समझ रहा हूँ या नहीं

  • मुझे लगता है type systems पर भी 80/20 rule लागू होता है, अगर इसे बहुत ज़्यादा आगे बढ़ाया जाए तो library का उपयोग बोझिल हो जाता है और वास्तविक फायदा भी बहुत कम रह जाता है, UUID या String तो परिचित हैं, लेकिन AccountID, UserID जैसे types नए लगते हैं इसलिए उन्हें सीखने की लागत होती है, elaborate type system का मूल्य हो भी सकता है और नहीं भी (खासकर अगर tests पर्याप्त हों), संबंधित संदर्भ

    • वैसे भी software इस्तेमाल करने के लिए Account या User क्या है यह जानना ही पड़ता है, इसलिए getAccountById जैसा function जो AccountId लेता है, वह UUID लेने वाले function से समझने में ज़्यादा कठिन नहीं है

    • असल में String तो सिर्फ bytes का एक संग्रह है, उसका अपने आप में कोई अर्थ नहीं, लेकिन AccountID हो तो ज़्यादातर लोग समझ जाते हैं कि यह 'account का ID' है, अगर असली internal representation जाननी हो तो type definition देखी जा सकती है, लेकिन ज़्यादातर संदर्भों में AccountID क्या है इतना जानना काफी है, type का मकसद ही यह है कि साफ़ नाम होने पर उपयोग करते समय कम भ्रम हो, grugbrain.dev वाला लिंक तो उल्टा बहुत बुनियादी स्तर की बात करता है, grug brain होता तो शायद इस स्तर के type separation का समर्थन करता

    • foo(UUID, UUID) की तुलना में foo(AccountId, UserId) बहुत बेहतर है, यह self-descriptive है, और गलती से arguments की order बदलकर call करने पर compiler पकड़ सकता है, जटिल data structures में भी नया type बनाए बिना चीज़ें अधिक स्पष्ट हो जाती हैं

      Map<UUID, List<UUID>>
      Map<AccountId, List<UserId>>
      
    • "UUID या String तो पहले से familiar हैं" इस बात पर, वास्तव में UUID को GUIDv1, UUIDv4, UUIDv7 आदि किस रूप में store/convert किया जाता है यह समझना आसान नहीं होता, मेरे अनुभव में Java+MS SQL संयोजन में UUID और uniqueidentifier के बीच conversion करते समय endian conversion की समस्या के कारण हाथ से ठीक करना पड़ा था, शायद यह database timezone auto-conversion की उलझनों जैसा ही मामला है

    • सच तो यह है कि ऐसे types के बारे में जानना वैसे भी ज़रूरी था, नहीं तो गलत data सीधे function में पास हो सकता था

  • हाल ही में हमारी टीम ने भी C++ code में कई mixed numeric values वाले हिस्सों पर types लागू किए, इसकी शुरुआत एक bug खोजकर ठीक करते समय safe types लाने से हुई, और फिर पता चला कि ऐसी ही गलत value usage तीन और जगहों पर मौजूद थी

  • mp-units(mp-units आधिकारिक दस्तावेज़) library इस तरह की physical unit problems पर केंद्रित एक अच्छा उदाहरण है, मजबूत unit types इस्तेमाल करने से safety मिलती है, जटिल unit conversion logic अपने-आप संभल जाता है, और generic code से अलग-अलग units को handle किया जा सकता है, मैंने इसे Prolog की दुनिया में लाने की कोशिश की थी लेकिन आसपास के साथियों ने ज़्यादा रुचि नहीं दिखाई, Prolog के लिए उदाहरण

    • मैंने पहले एक project पर काम किया था जहाँ अलग-अलग physical quantities (distance, speed, temperature, pressure आदि) संभालने पड़ते थे, लेकिन सब कुछ सिर्फ float के रूप में पास किया जाता था, इसलिए distance value को speed की जगह दे दो तो compile time पर कुछ नहीं होता और bug runtime पर दिखता, units (जैसे km/h बनाम miles/h) गलत पास होने पर भी यही स्थिति थी, मैं types बढ़ाकर development stage में ही ऐसी समस्याएँ पकड़ना चाहता था, लेकिन उस समय junior था और दूसरों को मनाना कठिन था

    • मैंने इस डर से physical units के लिए types लागू करने का विचार छोड़ दिया था कि कहीं यह बहुत जटिल न हो जाए, लेकिन अब mp-units को देखने का इरादा है, खासकर इसलिए कि variables किस unit में हैं यह साफ़ नहीं लिखा होता और इसी वजह से अक्सर समस्याएँ होती हैं, बाहरी data या standard functions वगैरह में unit annotation न होना आम बात है

  • C# में types कुछ इस तरह बनाए जाते हैं

    readonly struct Id32<M> {
      public readonly int Value { get; }
    }
    

    फिर

    public sealed class MFoo { }
    public sealed class MBar { }
    Id32<MFoo> x;
    Id32<MBar> y;
    

    इस तरह अलग-अलग integer IDs को अलग पहचान के साथ इस्तेमाल किया जा सकता है, इसे IdGuid या IdString तक बढ़ाया जा सकता है और नया marker type(M) जोड़ने के लिए सिर्फ एक लाइन चाहिए, TypeScript और Rust में भी इसी तरह के variants इस्तेमाल होते हैं

    • मैंने भी ऐसा ही pattern इस्तेमाल किया है, और अगर ID int हो तो enum सबसे कम friction वाला विकल्प लगता है, लेकिन यह बहुत confusing हो सकता है इसलिए इसे असली code में नहीं डाला, संबंधित चर्चा

    • इस pattern को 'phantom type' कहा जाता है क्योंकि MFoo या MBar की value runtime पर मौजूद नहीं होती

    • इस उपयोग के लिए Vogen जैसी libraries भी हैं, Vogen का अर्थ Value Object Generator है, और यह source code generation के ज़रिए Value object types जोड़ने में मदद करती है, readme में ऐसी ही दूसरी libraries और links भी दिए गए हैं

  • मैंने यह तरीका पहले भी देखा था लेकिन इसका उद्देश्य नहीं समझा था, आज भी जब मैं तीन string arguments लेने वाला function लिख रहा था तो सोच रहा था कि type parsing को call site पर force करूँ या function के अंदर, लेकिन वास्तव में parsing value की ज़रूरत ही नहीं थी, इसलिए यह वही जवाब निकला जिसकी मुझे तलाश थी, शायद इस साल मेरी coding style पर इसका सबसे बड़ा असर पड़ेगा

  • मेरे दोस्त Lukas ने इस विचार को 'Safety Through Incompatibility' के रूप में लिखा है, मैंने यह pattern golang code में हर जगह लागू किया है और यह बहुत उपयोगी लगा, यह गलत ID पास होने की समस्या को जड़ से रोक देता है
    संबंधित लेख 1
    संबंधित लेख 2

  • Swift में typealias keyword है, लेकिन अगर underlying type वही हो तो वे एक-दूसरे में स्वतंत्र रूप से convert हो सकते हैं, इसलिए व्यावहारिक रूप से यह इस उद्देश्य के लिए उपयुक्त नहीं है, wrapper struct Swift में काफ़ी idiomatic है और ExpressibleByStringLiteral का उपयोग करें तो कुछ हद तक सुविधाजनक भी है, लेकिन अच्छा होता अगर कोई नया keyword जैसे strong typealias या typecopy होता जिससे यह बताया जा सके कि "यह सिर्फ String है, लेकिन खास अर्थ वाला String है, इसलिए इसे दूसरे String के साथ mix मत करो"

    • वास्तव में ज़्यादातर भाषाएँ ऐसी ही हैं, जैसे rust/c/c++ भी, और Go वाले उदाहरण की तरह जब wrapper type न बनानी पड़े तो अच्छा लगता है, C++ में अगर constructor को explicit न किया जाए तो int को Foo type की जगह आसानी से पास किया जा सकता है, इसलिए और सावधानी चाहिए

    • सिद्धांत में यह elegant लगता है, लेकिन वास्तविक उपयोग में यह जटिल हो सकता है, जैसे C++ में std::cout में डालना, या उन third-party functions और extension points के साथ compatibility जो पहले से String लेते हैं

    • Haskell में यह concept newtype के रूप में है, OOP भाषाओं में अगर type final न हो तो subclass बनाकर मनचाहा behavior जोड़ना या specialize करना आसान होता है, अतिरिक्त wrapper या boxing के बिना यह सस्ता और सरल है, लेकिन Java में String final है इसलिए यह तरीका कठिन हो जाता है, String को खुद specialize करना आसान नहीं

    • खास तौर पर जानना चाहूँगा कि तुम चाहते हो कि यह struct wrapper से अलग कैसे काम करे

 
brain1401 2025-07-28

Rust में भी इसे इसी तरह इस्तेमाल करते हैं, तो निश्चित रूप से यह अच्छा लगता है।

 
regentag 2025-07-28

अगर आप ऐसी भाषा का इस्तेमाल करते हैं जिसमें type system अच्छा हो, तो शायद ऐसी चीज़ें भी रोकी जा सकती थीं..
सितंबर 1999 में NASA Mars Climate Orbiter का लापता होना

  • बल की मात्रा को व्यक्त करते समय pound unit इस्तेमाल करने वाले module और Newton unit इस्तेमाल करने वाले module के बीच data integration की समस्या के कारण orbiter को गलत तरीके से नियंत्रित किया गया और वह दुर्घटनाग्रस्त हो गया।