क्या किसी भी भाषा में एक इकहरी बूलियन टॉगल ऑपरेटर है?


141

तो यह एक सैद्धांतिक सवाल है। C ++ और भाषाएँ (इन) सीधे इस पर आधारित (Java, C #, PHP) में पहले ऑपरेटर के लिए अधिकांश बाइनरी ऑपरेटरों का परिणाम असाइन करने के लिए शॉर्टकट ऑपरेटर हैं , जैसे कि

a += 3;   // for a = a + 3
a *= 3;   // for a = a * 3;
a <<= 3;  // for a = a << 3;

लेकिन जब मैं एक बूलियन अभिव्यक्ति को टॉगल करना चाहता हूं तो मैं हमेशा खुद को कुछ लिखता हुआ पाता हूं

a = !a;

जब aएक लंबी अभिव्यक्ति की तरह गुस्सा आता है।

this.dataSource.trackedObject.currentValue.booleanFlag =
    !this.dataSource.trackedObject.currentValue.booleanFlag;

(हाँ, Demeter कानून, मुझे पता है)।

इसलिए, मैं सोच रहा था, क्या एक गैर-बूलियन टॉगल ऑपरेटर के साथ कोई भाषा है जो मुझे उदाहरण के लिए a = !aअभिव्यक्ति को दोहराए बिना संक्षिप्त करने की अनुमति देगा।a

!=a;  
// or
a!!;

मान लेते हैं कि हमारी भाषा का एक उचित बूलियन प्रकार है (जैसे boolC ++) और यह aउस प्रकार का है (इसलिए कोई C- शैली नहीं int a = TRUE)।

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


(नोट: मुझे पता है कि कुछ लोगों को राय है कि काम उपयोग नहीं करना चाहिए के हैं =और कि ++और +=उपयोगी ऑपरेटरों लेकिन डिजाइन खामियां नहीं हैं, हम बस यह मान रहा है मैं क्यों वे bools का विस्तार नहीं होगा पर उन्हें और ध्यान देने के साथ खुश हूँ)।


31
एक समारोह के बारे में क्या void Flip(bool& Flag) { Flag=!Flag; }आपकी लंबी अभिव्यक्ति को छोटा करता है।
हार्पर

72
this.dataSource.trackedObject.currentValue.booleanFlag ^= 1;
KamilCuk

13
कोड को सरल बनाने के लिए लंबी अभिव्यक्तियों को सौंपा जा सकता है
क्वेंटिन 2

6
@KamilCuk यह काम कर सकता है, लेकिन आप प्रकार मिलाते हैं। आप एक पूर्णांक एक बूल को असाइन करते हैं।
हार्पर

7
@ user463035818 *= -1हालांकि, जो किसी कारण से मैं अधिक सहज ज्ञान युक्त है ^= true
कॉम्पिटिशन

जवाबों:


15

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

टीएल; डीआर स्पष्ट रूप से नहीं, लेकिन स्विफ्ट आपको एक लागू करने देता है। यदि आप केवल यह देखना चाहते हैं कि यह कैसे किया जाता है, तो आप इस उत्तर के नीचे स्क्रॉल कर सकते हैं।


विभिन्न भाषाओं की सुविधाओं के लिए (त्वरित) खोज के बाद, मैं यह कहना सुरक्षित महसूस करूंगा कि किसी भी भाषा ने इस ऑपरेटर को एक सख्त म्यूटिंग-इन-ऑपरेशन के रूप में लागू नहीं किया है (यदि आप एक पाते हैं तो मुझे सही करें)। तो अगली बात यह देखने की होगी कि क्या ऐसी भाषाएँ हैं जो आपको एक बनाने देती हैं। इसके लिए दो चीजों की आवश्यकता होगी:

  1. कार्यों के साथ (यूनिरी) ऑपरेटरों को लागू करने में सक्षम होना
  2. उक्त कार्यों को पास-बाय-रेफ़र तर्क देने की अनुमति देता है (ताकि वे सीधे अपनी दलीलें म्यूट कर सकें)

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


हालांकि, कम से कम एक भाषा है जो सभी आवश्यक बक्से को टिक करती है: स्विफ्ट । हालांकि कुछ लोगों ने आगामी .toggle () सदस्य फ़ंक्शन से लिंक किया है , आप अपने खुद के ऑपरेटर भी लिख सकते हैं, जो वास्तव में इनवॉइस तर्कों का समर्थन करता है। भौचक्का होना:

prefix operator ^

prefix func ^ (b: inout Bool) {
    b = !b
}

var foo = true
print(foo)
// true

^foo

print(foo)
// false

6
भाषा इसे प्रदान करेगी: github.com/apple/swift-evolution/blob/master/proposals/…
Cristik

3
हां, लेकिन प्रश्न विशेष रूप से ऑपरेटर के लिए पूछा गया है , न कि सदस्य कार्य के लिए।
लॉरी पीस्पैन

4
"न तो रस्ट करता है" => हाँ यह करता है
Boiethios

3
@Boiethios धन्यवाद! जंग के लिए संपादित - केवल कस्टम प्रकारों के लिए अतिभारित ऑपरेटरों को अनुमति देता है, हालांकि, कोई पासा नहीं।
लॉरी पाइस्पैन

3
@LauriPiispanen नियम सामान्य से अधिक है, और अनाथ नियम के कारण , FYI करें
Boiethios

143

बूलियन बिट टॉगल करना

... कि मुझे a = !a अभिव्यक्ति को दोहराने के बिनाa संक्षिप्त करने की अनुमति होगी ...

यह दृष्टिकोण वास्तव में एक शुद्ध "म्यूटिंग फ्लिप" ऑपरेटर नहीं है, लेकिन ऊपर आपके मानदंड को पूरा करता है; अभिव्यक्ति का दाहिना हाथ चर को शामिल नहीं करता है।

बूलियन एक्सओआर असाइनमेंट (जैसे ^=) के साथ कोई भी भाषा a, एक्सओआर असाइनमेंट के माध्यम से, चर के वर्तमान मूल्य को कहने की अनुमति देती है true:

// type of a is bool
a ^= true;  // if a was false, it is now true,
            // if a was true, it is now false

जैसा कि नीचे दिए गए टिप्पणियों में @cmaster द्वारा बताया गया है, ऊपर की मानें aप्रकार की हैं bool, और उदाहरण के लिए पूर्णांक या सूचक नहीं। यदि aवास्तव में कुछ और है (उदाहरण के boolलिए "सत्य" या "मिथ्या" मूल्य का कुछ गैर- मूल्यांकन, थोड़ा प्रतिनिधित्व के साथ जो क्रमशः 0b1या नहीं 0b0है), तो ऊपर पकड़ नहीं है।

एक ठोस उदाहरण के लिए, जावा एक ऐसी भाषा है जहाँ यह अच्छी तरह से परिभाषित है और किसी भी मौन रूपांतरण के अधीन नहीं है। नीचे से @ Boann की टिप्पणी का उद्धरण:

जावा में, ^और ^=स्पष्ट रूप से बूलियन्स के लिए और पूर्णांकों के लिए व्यवहार को परिभाषित किया है ( 15.22.2। बूलियन तार्किक ऑपरेटर्स &, ^और| ), जहां या तो ऑपरेटर के दोनों ओर बूलियन्स होना चाहिए, या दोनों पक्षों पूर्णांक होना चाहिए। उन प्रकारों के बीच कोई मौन रूपांतरण नहीं है। तो यह चुपचाप खराबी के लिए नहीं जा रहा है अगर aएक पूर्णांक के रूप में घोषित किया जाता है, बल्कि एक संकलन त्रुटि दे। तो a ^= true;जावा में सुरक्षित और अच्छी तरह से परिभाषित है।


स्विफ्ट: toggle()

स्विफ्ट 4.2 के अनुसार, निम्नलिखित विकास प्रस्ताव को स्वीकार कर लिया गया है और कार्यान्वित किया गया है:

यह स्विफ्ट toggle()के Boolप्रकार में एक देशी फ़ंक्शन जोड़ता है ।

toggle()

बूलियन चर के मान को टॉगल करता है।

घोषणा

mutating func toggle()

विचार-विमर्श

इस विधि का उपयोग बूलियन मान को टॉगल trueकरने के लिए falseया उससे falseकरने के लिए करें true

var bools = [true, false]

bools[0].toggle() // bools == [false, false]

यह एक ऑपरेटर नहीं है, प्रति se, लेकिन बूलियन टॉगल के लिए एक भाषा देशी दृष्टिकोण की अनुमति देता है।


3
टिप्पणियाँ विस्तारित चर्चा के लिए नहीं हैं; इस वार्तालाप को बातचीत में स्थानांतरित कर दिया गया है ।
सैमुअल Liew

44

C ++ में ऑपरेटरों के अर्थ को पुनर्परिभाषित करने का कार्डिनल पाप करना संभव है। इसे ध्यान में रखते हुए, और ADL का थोड़ा सा, हम सभी को अपने उपयोगकर्ता पर तबाही मचाने की आवश्यकता है:

#include <iostream>

namespace notstd
{
    // define a flag type
    struct invert_flag {    };

    // make it available in all translation units at zero cost
    static constexpr auto invert = invert_flag{};

    // for any T, (T << invert) ~= (T = !T)    
    template<class T>
    constexpr T& operator<<(T& x, invert_flag)
    {
        x = !x;
        return x;
    }
}

int main()
{
    // unleash Hell
    using notstd::invert;

    int a = 6;
    std::cout << a << std::endl;

    // let confusion reign amongst our hapless maintainers    
    a << invert;
    std::cout << a << std::endl;

    a << invert;
    std::cout << a << std::endl;

    auto b = false;
    std::cout << b << std::endl;

    b << invert;
    std::cout << b << std::endl;
}

अपेक्षित उत्पादन:

6
0
1
0
1

9
"ऑपरेटरों के अर्थ को पुनर्परिभाषित करने का कार्डिनल पाप" - मुझे लगता है कि आप अतिरंजित थे, लेकिन यह वास्तव में मौजूदा ऑपरेटरों के लिए नए अर्थों को पुन: पेश करने के लिए एक कार्डिनल पाप नहीं है।
कोनराड रुडोल्फ

5
@KonradRudolph मेरा इस से क्या तात्पर्य है कि एक ऑपरेटर को अपने सामान्य अंकगणित या तार्किक अर्थ के संबंध में तार्किक अर्थ निकालना चाहिए। 2 स्ट्रिंग्स के लिए 'ऑपरेटर +' तर्कसंगत है, क्योंकि इसके अलावा या संचय के लिए समरूपता समान है (हमारे दिमाग की आंख में)। operator<<एसटीएल में मूल दुर्व्यवहार के कारण 'धारा प्रवाहित' होने का मतलब है। इसका स्वाभाविक रूप से मतलब यह नहीं होगा कि 'आरएचएस पर परिवर्तन कार्य को लागू करें', जो अनिवार्य रूप से मैंने यहां के लिए इसे फिर से लागू किया है।
रिचर्ड हॉजेस

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

8
<<एक बुरा अधिभार की तरह लगता है। मैं करता हूँ !invert= x;;)
यक - एडम नेवरामॉन्ट

12
@ यक-आदमनेवरुमोंट LOL, अब आपने मुझे शुरू कर दिया है: godbolt.org/z/KIkesp
रिचर्ड होजेस

37

जब तक हम विधानसभा भाषा को शामिल करते हैं ...

उल्लिखित

INVERT एक बिटवाइज़ पूरक के लिए।

0= तार्किक (सत्य / असत्य) पूरक के लिए।


4
तर्कपूर्ण, हर स्टैक-ओरिएंटेड भाषा में एक यूनरी notएक "टॉगल" ऑपरेटर है :-)
बर्गी

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

31

C99 boolघटने से वांछित प्रभाव होगा, जैसा कि bitकुछ छोटे-माइक्रोकंट्रोलर बोलियों में समर्थित प्रकारों को बढ़ाना या घटाना होगा (जो मैंने बिट्स को एकल-बिट विस्तृत बिटफ़िल्ड के रूप में देखा है, इसलिए सभी को 0 और सभी को काट दिया जाता है। विषम संख्या 1)। मैं विशेष रूप से इस तरह के उपयोग की सिफारिश नहीं करूंगा, क्योंकि मैं इस boolप्रकार के शब्दार्थों का बहुत बड़ा प्रशंसक नहीं हूं [IMHO, प्रकार में यह निर्दिष्ट किया जाना चाहिए कि boolकिसी भी मान को 0 या 1 के अलावा संग्रहीत किया जाता है, हालांकि जब भी पढ़ा जाए तो व्यवहार किया जा सकता है। यह एक अनिर्दिष्ट (अनिवार्य रूप से सुसंगत नहीं) पूर्णांक मूल्य रखता है; यदि कोई प्रोग्राम पूर्णांक मान को संग्रहीत करने का प्रयास कर रहा है जो 0 या 1 के रूप में नहीं जाना जाता है, तो !!उसे पहले उपयोग करना चाहिए ]।


2
C ++ bool 17 के साथ C ++ ने यही काम किया ।
डेविस हेरिंग

31

2
मुझे नहीं लगता कि यह काफी ओप मन में था, यह मानते हुए कि x86 असेंबली है। उदा। en.wikibooks.org/wiki/X86_Assembly/Logic ; here edx would be 0xFFFFFFFE because a bitwise NOT 0x00000001 = 0xFFFFFFFE
BurnsBA

8
आप इसके बजाय सभी बिट्स का उपयोग कर सकते हैं: 0x00000000 = 0xFFFFFFFF
एड्रियन

5
खैर, हां, हालांकि मैं बूलियन और बिटवाइज़ ऑपरेटरों के बीच अंतर को आकर्षित करने की कोशिश कर रहा था। चूंकि ऑप्स सवाल में कहते हैं, मान लें कि भाषा में एक अच्छी तरह से परिभाषित बूलियन प्रकार है: "(इसलिए कोई सी-शैली इंट ए = ट्रू) नहीं है।"
BurnsBA

5
@BurnsBA: वास्तव में, विधानसभा भाषाओं में अच्छी तरह से परिभाषित सत्य / झूठे मूल्यों का एक भी सेट नहीं है। कोड-गोल्फ पर, इस बात पर बहुत चर्चा की गई है कि विभिन्न भाषाओं में बूलियन समस्याओं के लिए आपको कौन से मानों की अनुमति है। चूंकि एएसएम का कोई if(x)निर्माण नहीं है , इसलिए यह 0 / -1 को असत्य / सत्य के रूप में अनुमति देने के लिए पूरी तरह से उचित है, जैसे कि SIMD तुलना ( felixcloutier.com/x86/PCMPEQB:PCMPEQW:PCMPEQD.html )। लेकिन आप सही हैं कि अगर आप इसे किसी अन्य मूल्य पर उपयोग करते हैं तो यह टूट जाता है।
पीटर कॉर्ड्स

4
एकल बूलियन प्रतिनिधित्व के लिए यह कठिन है कि PCMPEQW का परिणाम 0 / -1 है, लेकिन SETcc का परिणाम 0 / + 1 है।
यूजीन स्टायर

28

मुझे लगता है कि आप इस पर पूरी तरह से आधारित भाषा का चयन नहीं करने जा रहे हैं :-) किसी भी मामले में, आप इसे C ++ में कुछ के साथ कर सकते हैं:

inline void makenot(bool &b) { b = !b; }

उदाहरण के लिए निम्नलिखित पूरा कार्यक्रम देखें:

#include <iostream>

inline void makenot(bool &b) { b = !b; }

inline void outBool(bool b) { std::cout << (b ? "true" : "false") << '\n'; }

int main() {
    bool this_dataSource_trackedObject_currentValue_booleanFlag = false;
    outBool(this_dataSource_trackedObject_currentValue_booleanFlag);

    makenot(this_dataSource_trackedObject_currentValue_booleanFlag);
    outBool(this_dataSource_trackedObject_currentValue_booleanFlag);

    makenot(this_dataSource_trackedObject_currentValue_booleanFlag);
    outBool(this_dataSource_trackedObject_currentValue_booleanFlag);
}

यह आउटपुट, जैसा कि अपेक्षित था:

false
true
false

2
क्या आप भी करना चाहेंगे return b = !b? कोई पढ़ रहा है foo = makenot(x) || yया सिर्फ एक साधारण foo = makenot(bar)मान सकता है कि makenotयह एक शुद्ध कार्य था, और मान लें कि कोई साइड-इफेक्ट नहीं था। एक बड़ी अभिव्यक्ति के अंदर एक साइड-इफ़ेक्ट को दफनाना शायद खराब शैली है, और गैर-शून्य रिटर्न प्रकार का एकमात्र लाभ इसे सक्षम कर रहा है।
पीटर कॉर्ड्स

2
@MatteoItalia सुझाव देता है template<typename T> T& invert(T& t) { t = !t; return t; } , जिसे टेम्पलेट किया जा रहा है / से परिवर्तित किया जाएगा boolयदि इसे गैर- boolऑब्जेक्ट पर उपयोग किया जाता है । अगर अच्छा या बुरा है तो IDK शायद अच्छा है।
पीटर कॉर्ड्स

22

पोस्टस्क्रिप्ट , एक जा रहा है concatenative , ढेर उन्मुख आगे की तरह भाषा, एक एकल टॉगल, है नहींनहीं ऑपरेटर ढेर के शीर्ष पर मूल्य टॉगल करता है। उदाहरण के लिए,

true    % push true onto the stack
not     % invert the top of stack
        % the top of stack is now false

देखें पोस्टस्क्रिप्ट भाषा संदर्भ मैनुअल (पीडीएफ) , पी। 458।


21

Visual Basic.Net एक्सटेंशन पद्धति के माध्यम से इसका समर्थन करता है।

एक्सटेंशन विधि को इस तरह परिभाषित करें:

<Extension>
Public Sub Flip(ByRef someBool As Boolean)
    someBool = Not someBool
End Sub

और फिर इसे इस तरह से कॉल करें:

Dim someVariable As Boolean
someVariable = True
someVariable.Flip

तो, आपका मूल उदाहरण कुछ इस तरह दिखाई देगा:

me.DataSource.TrackedObject.CurrentValue.BooleanFlag.Flip

2
हालांकि यह काम करता है क्योंकि लेखक जिस शॉर्टहैंड की तलाश कर रहा था, निश्चित रूप से, उसे लागू करने के लिए आपको दो ऑपरेटरों का उपयोग करना होगा Flip(): =और Not। यह जानना दिलचस्प है कि कॉलिंग के मामले में SomeInstance.SomeBoolean.Flipयह काम करता है भले ही SomeBooleanवह एक संपत्ति हो, जबकि समतुल्य सी # कोड संकलित नहीं होगा।
BACON

14

जंग में, आप गुण को लागू करने वाले प्रकारों का विस्तार करने के लिए अपना खुद का लक्षण बना सकते हैं Not:

use std::ops::Not;
use std::mem::replace;

trait Flip {
    fn flip(&mut self);
}

impl<T> Flip for T
where
    T: Not<Output = T> + Default,
{
    fn flip(&mut self) {
        *self = replace(self, Default::default()).not();
    }
}

#[test]
fn it_works() {
    let mut b = true;
    b.flip();

    assert_eq!(b, false);
}

आप ^= trueसुझाव के रूप में भी उपयोग कर सकते हैं , और जंग के मामले में, ऐसा करने के लिए कोई संभावित मुद्दा नहीं है क्योंकि falseसी या सी ++ में "प्रच्छन्न" पूर्णांक नहीं है:

fn main() {
    let mut b = true;
    b ^= true;
    assert_eq!(b, false);

    let mut b = false;
    b ^= true;
    assert_eq!(b, true);
}


3

C # में :

boolean.variable.down.here ^= true;

बूलियन ^ ऑपरेटर XOR है, और XORing सच के साथ inverting के समान है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.