आप किसी शर्त में असाइनमेंट का उपयोग क्यों करेंगे?


80

कई भाषाओं में असाइनमेंट शर्तों में कानूनी हैं। मैंने इसके पीछे का कारण कभी नहीं समझा। आप क्यों लिखेंगे:

if (var1 = var2) {
  ...
}

के बजाय:

var1 = var2;
if (var1) {
  ...
}

क्या यह सवाल वास्तव में इतना भाषा-अज्ञेयवादी है? इससे कौन सी भाषाएं प्रभावित होती हैं? मुझे पता है कि C और C ++ हैं, और क्या हैं?
वुल्फ

जवाबों:


115

यदि कथन की तुलना में यह लूप के लिए अधिक उपयोगी है।

while( var = GetNext() )
{
  ...do something with var 
}

जो अन्यथा लिखना होता

var = GetNext();
while( var )
{
 ...do something
 var = GetNext();
}

14
मैं सहमत हूं - लेकिन लिखूंगा: जबकि ((var = GetNext ())! = 0) {...} दो बार बिना सोचे-समझे आंशिक रूप से जीसीसी शिकायत करता है अगर मैं अपने डिफ़ॉल्ट संकलन विकल्पों के साथ नहीं हूं।
जोनाथन लेफ्लर

1
सच। मान लें कि आप ऐसी भाषा का उपयोग कर रहे हैं जो लूप घोषणाओं का समर्थन करती है, और आप पहले से ही लूप के बाहर के संस्करण का उपयोग नहीं कर रहे हैं।
गेराल्ड

1
कुछ भाषाओं में, जैसे ANSI C, स्कूपिंग नियम इस दृष्टिकोण की अनुमति नहीं देते, @KerrekSB
wirrbel

7
@wirrbel: आपका मतलब एएनएसआई सी है, 1989 से? जैसे कि उनके पास स्टीम इंजन और पंच कार्ड कब थे? यह मामला हो सकता है, लेकिन क्या यह प्रासंगिक है?
केरेक एसबी

3
यह चेतावनी इसलिए नहीं है क्योंकि थोड़ी देर में असाइनमेंट में कुछ गड़बड़ है, बल्कि इसलिए कि जब आप वास्तव में तुलना करने का मतलब रखते हैं तो असाइनमेंट करना एक सामान्य बग है। यदि आप चेतावनी से छुटकारा पाना चाहते हैं तो आप @Jonathan Leffler के सुझाव के बराबर JS कर सकते हैं। व्यक्तिगत रूप से मैं शायद यह करूँगी कि जावास्क्रिप्ट सत्य नियमों का मैं कितना अविश्वास करता हूँ :) यह भी C # और जावा जैसी कुछ भाषाओं में ध्यान दिया जाना चाहिए जो एकमात्र तरीका है।
गेराल्ड

33

मुझे यह उन क्रियाओं की जंजीरों में सबसे अधिक उपयोगी लगता है जिनमें अक्सर त्रुटि का पता लगाना आदि शामिल हैं।

if ((rc = first_check(arg1, arg2)) != 0)
{
    report error based on rc
}
else if ((rc = second_check(arg2, arg3)) != 0)
{
    report error based on new rc
}
else if ((rc = third_check(arg3, arg4)) != 0)
{
    report error based on new rc
}
else
{
    do what you really wanted to do
}

विकल्प (शर्त में असाइनमेंट का उपयोग नहीं करना) है:

rc = first_check(arg1, arg2);
if (rc != 0)
{
    report error based on rc
}
else
{
    rc = second_check(arg2, arg3);
    if (rc != 0)
    {
        report error based on new rc
    }
    else
    {
        rc = third_check(arg3, arg4);
        if (rc != 0)
        {
            report error based on new rc
        }
        else
        {
            do what you really wanted to do
        }
    }
}

प्रचलित त्रुटि जाँच के साथ, विकल्प पृष्ठ के आरएचएस को बंद कर सकता है जबकि असाइनमेंट-इन-सशर्त संस्करण ऐसा नहीं करता है।

त्रुटि जाँच भी 'क्रियाओं' हो सकता है - first_action(), second_action(), third_action()- ज़ाहिर है, बल्कि सिर्फ चेकों से। यही है, उन्हें उस प्रक्रिया में चरणों की जांच की जा सकती है जो फ़ंक्शन का प्रबंधन कर रहा है। (अधिकांश बार मैं जिस कोड के साथ काम करता हूं, वह फ़ंक्शन प्री-कंडीशन चेक की लाइनों के साथ होता है, या फ़ंक्शन के लिए आवश्यक मेमोरी आवंटन या इसी तरह की लाइनों के साथ होता है)।


हाँ, मैंने वास्तव में अत्यधिक घोंसले से बचने के लिए ऐसा किया था और फिर यह देखने के लिए ऑनलाइन खोज की कि क्या यह एक आम बात है। अंत में मैंने इसके खिलाफ फैसला किया क्योंकि मेरे पास वास्तव में केवल एक और मामला था, लेकिन यह काम में शर्त लगाने के लिए एक वैध कारण जैसा लगता है।
इब्राहिम

सहकर्मियों को इससे नफरत है! मेरे लिए, कम से कम ज्यादातर मामलों में, विशालकाय पेड़ या कई रिटर्न की तुलना में कहीं अधिक बनाए रखने योग्य है। मैं एक समारोह से एकल वापसी पसंद करता हूं ...
नाथन

एक उचित उदाहरण, acompanion ब्लॉक पैटर्न को स्पष्ट, आत्म-व्याख्यात्मक बनाते हैं। लेकिन, ठीक है, इन-ब्लॉक ("छद्म") कोड थोड़ा बदसूरत दिखता है, और उलटा स्टाइल ( आप वास्तव में अंत में क्या करना चाहते थे ) यह महान नहीं है।
वुल्फ

31

यदि आप किसी फ़ंक्शन को कॉल कर रहे हैं तो यह अधिक उपयोगी है:

if (n = foo())
{
    /* foo returned a non-zero value, do something with the return value */
} else {
    /* foo returned zero, do something else */
}

ज़रूर, आप बस n = foo () डाल सकते हैं; एक अलग बयान पर तो अगर (एन), लेकिन मुझे लगता है कि उपरोक्त एक काफी पठनीय मुहावरा है।


3
मुझे लगता है कि आपको इसे कोष्ठक में संलग्न करना चाहिए या जीसीसी से शिकायत करनी चाहिए: चेतावनी: सत्य मूल्य के रूप में उपयोग किए जाने वाले आस-पास के कोष्ठकों का सुझाव दें -Warentheses] इस तरह: अगर ((n = foo ())) {// वापसी मूल्य के साथ कुछ } और {// फू शून्य / NULL लौटा, कुछ और करें}
Fabio Pozzi

23

यह उपयोगी हो सकता है यदि आप एक फ़ंक्शन को कॉल कर रहे हैं जो त्रुटि या (आप कर रहे हैं) को इंगित करने के लिए डेटा को फ़्लैग पर काम करने के लिए या ध्वज पर लौटाते हैं।

कुछ इस तरह:

while ((c = getchar()) != EOF) {
    // process the character
}

// end of file reached...

व्यक्तिगत रूप से यह एक मुहावरा है जिसका मैं बहुत शौकीन नहीं हूँ, लेकिन कभी-कभी इसका विकल्प बदसूरत है।


13

यदि आप अनजाने में सत्य मान के रूप में असाइनमेंट का उपयोग करने का प्रयास करते हैं, तो जीसीसी आपको पता लगाने में मदद कर सकता है (-सभी के साथ)।

if ((n = foo())) {
   ...
}

यानी यह बताने के लिए कि आप वास्तव में क्या चाहते हैं, अतिरिक्त कोष्ठक का उपयोग करें।


1
जानकार अच्छा लगा। मुझे आशा है कि आपके सहकर्मी इसे उसी तरीके से पढ़ेंगे।
वुल्फ

1
मुझे? अच्छाई, मैं सच मान के रूप में असाइनमेंट का उपयोग करने की कोशिश नहीं करूंगा। मैं जिक्र कर रहा था कि जीसीसी क्या सिफारिश करता है।
जेस्पर

जीसीसी फोरट्रान का संकलन भी कर सकता है । शायद प्रोग्रामिंग भाषा के बारे में स्पष्ट हो?
पीटर मोर्टेंसन

9

स्टेटमेंट के whileबजाय लूप लिखते समय मुहावरा अधिक उपयोगी होता है if। एक ifबयान के लिए, आप इसे वर्णन के अनुसार तोड़ सकते हैं। लेकिन इस निर्माण के बिना, आपको या तो खुद को दोहराना होगा:

c = getchar();
while (c != EOF) {
    // ...
    c = getchar();
}

या एक लूप-एंड-डेढ़ संरचना का उपयोग करें:

while (true) {
    c = getchar();
    if (c == EOF) break;
    // ...
}

मैं आमतौर पर लूप-एंड-डेढ़ फॉर्म को प्राथमिकता देता हूं।


1
एक whileपाश के लिए, का उपयोग करना पसंद करते हैं:do { c = getchar(); ... } while (c != EOF);
स्कॉट एस

और forलूप्स का उपयोग इसके बजाय किया जा सकता है: for (char c = getchar(); c != EOF; c= getchar()) { /* do something with c */ }- यह सबसे संक्षिप्त है, और forहमेशा मुझे 'लूप' कहते हैं, शैलीगत रूप से। छोटे नकारात्मक पक्ष यह है कि आपको cदो बार लौटने वाले फ़ंक्शन को निर्दिष्ट करना होगा ।
स्कॉट एस

4

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


1
यदि (), जबकि (), और अन्य समान विवरणों में बिना असाइनमेंट के कोडिंग लागू करने के लिए यह एक निरंतर लड़ाई है। C / C ++ ऐसे साइड इफेक्ट्स के लिए कुख्यात हैं जो अक्सर बग्स के रूप में सामने आते हैं, खासकर जब हम ++ और ऑपरेटर्स को जोड़ते हैं।
एलेक्सिस विलके

1
पहला लिंक बेकार है: C या C ++ ऐसी भाषा नहीं है।
वुल्फ

3

उदाहरण के लिए, PHP में, SQL डेटाबेस परिणामों के माध्यम से लूपिंग के लिए उपयोगी है:

while ($row = mysql_fetch_assoc($result)) {
    // Display row
}

यह देखने में बहुत बेहतर है:

$row = mysql_fetch_assoc($result);
while ($row) {
    // Display row
    $row = mysql_fetch_assoc($result);
}

4
यह भी उस पाश से परे नहीं रहने वाली $ पंक्ति का साफ-सुथरा साइड-इफेक्ट है और इसलिए जल्द ही कचरा संग्रह के लिए पात्र है (जो कि जीसी वैसे भी करते हैं)।
डैरेन ग्रीव्स

2

अन्य लाभ जीडीबी के उपयोग के दौरान आता है। निम्न कोड में त्रुटि कोड ज्ञात नहीं है यदि हम एकल चरण में थे।

while (checkstatus() != -1) {
    // process
}

बल्कि

while (true) {
    int error = checkstatus();
    if (error != -1)
        // process
    else
        //fail
}

अब सिंगल स्टेप के दौरान हम जान सकते हैं कि चेकस्टेटस () से रिटर्न एरर कोड क्या था।


1
आपका मतलब है कि कोड डीबग करते समय यह अस्थायी परिवर्तनों के लिए सहायक हो सकता है?
वुल्फ

0

मुझे वैकल्पिक लौटाने वाले कार्यों के साथ यह बहुत उपयोगी लगता है ( boost::optionalया std::optionalC ++ 17 में):

std::optional<int> maybe_int(); // function maybe returns an int

if (auto i = maybe_int()) {
    use_int(*i);
}

यह मेरे चर के दायरे को कम करता है, कोड को अधिक कॉम्पैक्ट बनाता है और पठनीयता में बाधा नहीं डालता है (मुझे लगता है)।

संकेत के साथ भी:

int* ptr_int();

if (int* i = ptr_int()) {
    use_int(*i);
}

वैसे, यदि आप वेरिएबल्स के दायरे को सीमित करना चाहते हैं, तो आप इनिशियलाइज़र के साथ उपयोग कर सकते हैं :)
सिगनल

-3

कारण यह है की:

  1. प्रदर्शन में सुधार (कभी-कभी)

  2. कम कोड (हमेशा)

एक उदाहरण लें: एक विधि है someMethod()और ऐसी ifस्थिति में आप जांचना चाहते हैं कि विधि का रिटर्न मान है या नहीं null। यदि नहीं, तो आप फिर से रिटर्न वैल्यू का उपयोग करने जा रहे हैं।

If(null != someMethod()){
    String s = someMethod();
    ......
    //Use s
}

यह प्रदर्शन को बाधित करेगा क्योंकि आप एक ही विधि को दो बार बुला रहे हैं। इसके बजाय उपयोग करें:

String s;
If(null != (s = someMethod())) {
    ......
    //Use s
}

यह कौनसी भाषा है? यह C # या C ++ ("यदि" का कैपिटलाइज़ेशन) में संकलित नहीं होगा।
पीटर मोर्टेंसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.