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




language-agnostic bitwise-operators (8)

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

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;  
// or
a!!;

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

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

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


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

... कि मुझे a = !a अभिव्यक्ति को दोहराने के बिना a = !a लिए अनुमति देता a ...

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

बूलियन XOR असाइनमेंट वाली कोई भी भाषा (जैसे ^= ) किसी वेरिएबल के करंट वैल्यू को फ़्लिप करने की अनुमति देती a , XOR असाइनमेंट को 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 , और उदाहरण के लिए पूर्णांक या पॉइंटर नहीं है। यदि वास्तव में कुछ और है (उदाहरण के लिए "सत्य" या "मिथ्या" मूल्य का मूल्यांकन करने वाले कुछ गैर- bool , तो थोड़ा प्रतिनिधित्व के साथ, जो क्रमशः 0b1 या 0b0 नहीं है), उपरोक्त नहीं है।

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

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

स्विफ्ट: toggle()

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

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

toggle()

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

घोषणा

mutating func toggle()

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

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

var bools = [true, false]

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

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



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

जंग में, आप प्रकारों का विस्तार करने के लिए अपना स्वयं का गुण बना सकते हैं जो नोटरी गुण को लागू 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 का भी उपयोग कर सकते हैं, और Rust के मामले में, ऐसा करने के लिए कोई संभावित मुद्दा नहीं है, क्योंकि false C या C ++ की तरह "प्रच्छन्न" पूर्णांक नहीं है:

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

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

मैं मान रहा हूँ कि आप इस पर पूरी तरह से आधारित भाषा का चयन नहीं करने जा रहे हैं :-) किसी भी स्थिति में, आप इसे 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

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

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

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

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

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

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

prefix operator ^

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

var foo = true
print(foo)
// true

^foo

print(foo)
// false

C # में :

boolean.variable.down.here ^= true;

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


PostScript , फोर्थ की तरह समवर्ती, stack-oriented भाषा होने के नाते, एक यूरी टॉगल है, नहीं नहीं ऑपरेटर स्टैक के शीर्ष पर मूल्य टॉगल करता है। उदाहरण के लिए,

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

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





negation