143

So this is more of a theoretical question. C++ and languages (in)directly based on it (Java, C#, PHP) have shortcut operators for assigning the result of most binary operators to the first operand, such as

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

but when I want to toggle a boolean expression I always find myself writing something like

a = !a;

which gets annoying when a is a long expression like.

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

(yeah, Demeter's Law, I know).

So I was wondering, is there any language with a unary boolean toggle operator that would allow me to abbreviate a = !a without repeating the expression for a, for example

!=a;  
// or
a!!;

Let's assume that our language has a proper boolean type (like bool in C++) and that a is of that type (so no C-style int a = TRUE).

If you can find a documented source, I'd also be interested to learn whether e.g. the C++ designers have considered adding an operator like that when bool became a built-in type and if so, why they decided against it.


(Note: I know that some people are of the opinion that assignment should not use = and that ++ and += are not useful operators but design flaws; let's just assume I'm happy with them and focus on why they would not extend to bools).

CompuChip
  • 9,143
  • 4
  • 24
  • 48
  • 31
    What about a function `void Flip(bool& Flag) { Flag=!Flag; }` The shortens your long expression. – harper Aug 20 '18 at 08:50
  • 1
    You can write: `bool& flag=this.dataSource.trackedObject.currentValue.booleanFlag; flag = !flag;` – Martin Bonner supports Monica Aug 20 '18 at 08:51
  • 72
    `this.dataSource.trackedObject.currentValue.booleanFlag ^= 1;` – KamilCuk Aug 20 '18 at 08:51
  • 13
    long expressions can be assigned to references to simplify the code – Quentin 2 Aug 20 '18 at 08:51
  • 6
    @KamilCuk This might work, but you mixup types. You assign an integer to an bool. – harper Aug 20 '18 at 08:52
  • 3
    maybe having such an operator would be too confusing. Consider that there is also no unary negation for numbers (imho a much better analogon than `+=`) that modifies its operand. There is only a unary `-` and a `-=` that does something different. However, "because it would be too confusing" isnt never a good reason.... – 463035818_is_not_an_ai Aug 20 '18 at 08:55
  • 7
    @user463035818 there is `*= -1` though, which for some reason I find more intuitive than `^= true`. – CompuChip Aug 20 '18 at 09:07
  • 3
    .NET is open-source now. You could code it and do a pull request. Who knows? Maybe it'll get integrated. a!! looks like it could be a compliant unary operator. – Robear Aug 20 '18 at 15:17
  • 3
    @harper In many languages, such as C and C++, a `bool` is an integer. – Sneftel Aug 20 '18 at 15:29
  • 2
    In an OO language you shouldn't ask an object for a value or operate on one, you should ask it to do something for you. So this.dataSource.trackedObject.currentValue.booleanFlag would likely not work anyway, perhaps dataSource.flipTrackedObjectValue() would be better (Although obviously there are some constraints when combining libraries and user defined objects that might make this impossible as well, but SOME level of encapsulation would be nice). – Bill K Aug 20 '18 at 22:04
  • 2
    Why are you toggling the Boolean in place? The only uses for this I can think of are poor design practices. – jpmc26 Aug 20 '18 at 23:55
  • 1
    @CompuChip are you sure `*= -1` does the right thing? – Dawood ibn Kareem Aug 21 '18 at 00:03
  • 1
    @DawoodibnKareem that comment was a reply to "...Consider that there is also no unary negation for numbers ..." and yes I'm pretty sure that has the same effect as `-a` when `a` is a (signed) integer. – CompuChip Aug 21 '18 at 06:28
  • 1
    Remember that properties cannot be passed to ref methods and if I recall correctly don't work with these shorthand operators. – Ian Ringrose Aug 21 '18 at 08:34
  • 1
    @Sneftel: not exactly, `bool` is a distinct type which can only have value 0 or 1. It's implicitly convertible to integer, though, so `bool_var ^= 1` is `bool_var = (bool)( 1 ^ (int)bool_var )`. Any assignment or cast to `bool` booleanizes the value, like `!!x`. If you use `memcpy` to set the object representation of a `bool` to a byte that isn't a 0 or 1, using the value will be undefined behaviour. Most ABIs/calling conventions (e.g. x86-64 System V) say that compilers (and hand-written asm) are allowed to assume that a `bool` has a 0 or 1 value, not 0 / non-zero. – Peter Cordes Aug 21 '18 at 12:21
  • 2
    @PeterCordes In C, `_Bool` is listed as one of the "standard unsigned integer types". In C++, `bool` is one of the "integer types". It's true that it has a number of values much less than 2^its bit count, but that's allowed by the standard for other integer types as well. It gets a little confusing because its narrowing conversion doesn't match the semantics of either one, but both languages are clear that booleans are in the category of integral types. – Sneftel Aug 21 '18 at 12:29
  • 1
    (doesn't match the semantics of either signed or unsigned integral types, that is) – Sneftel Aug 21 '18 at 12:44
  • 3
    @jpmc26: Why shouldn't I toggle a bool in place? What "design practices" could be violated by such a harmless operation? – TonyK Aug 21 '18 at 22:25
  • 1
    @TonyK Because it probably means you're reusing the variable for different concepts or would be better off using some other criteria. The former means you have to evaluate what the intended meaning of the variable is in each context. The latter case (like maybe skipping values in a loop or something) would be better done by examining the modulo of the index or using a criteria on the data itself, since these are static properties of each iteration and don't depend on previous ones. The only usages I can think of are confusing or more likely to have a bug than other ways of doing them. – jpmc26 Aug 21 '18 at 22:50
  • 1
    @sneftel Nope, See at §4.7/4 from the C++ Standard. You find a Conversion between bool and int. Why would you need a Conversion If they would be identical? – harper Aug 22 '18 at 08:03
  • 1
    @harper There are conversions between all integer types. See, e.g... well, all of 4.7. I think you might be confusing "integer" with `int`. C++ has several integer types; `int` is one of them. (`bool` is another one of them.) – Sneftel Aug 22 '18 at 08:36

12 Answers12

145

Toggling the boolean bit

... that would allow me to abbreviate a = !a without repeating the expression for a ...

This approach is not really a pure "mutating flip" operator, but does fulfill your criteria above; the right hand side of the expression does not involve the variable itself.

Any language with a boolean XOR assignment (e.g. ^=) would allow flipping the current value of a variable, say a, by means of XOR assignment to true:

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

As pointed out by @cmaster in the comments below, the above assumes a is of type bool, and not e.g. an integer or a pointer. If a is in fact something else (e.g. something non-bool evaluating to a "truthy" or "falsy" value, with a bit representation that is not 0b1 or 0b0, respectively), the above does not hold.

For a concrete example, Java is a language where this is well-defined and not subject to any silent conversions. Quoting @Boann's comment from below:

In Java, ^ and ^= have explicitly defined behavior for booleans and for integers (15.22.2. Boolean Logical Operators &, ^, and | ), where either both sides of the operator must be booleans, or both sides must be integers. There's no silent conversion between those types. So it's not going to silently malfunction if a is declared as an integer, but rather, give a compile error. So a ^= true; is safe and well-defined in Java.


Swift: toggle()

As of Swift 4.2, the following evolution proposal has been accepted and implemented:

This adds a native toggle() function to the Bool type in Swift.

toggle()

Toggles the Boolean variable’s value.

Declaration

mutating func toggle()

Discussion

Use this method to toggle a Boolean value from true to false or from false to true.

var bools = [true, false]

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

This is not an operator, per se, but does allow a language native approach for boolean toggling.

Andre Pena
  • 56,650
  • 48
  • 196
  • 243
dfrib
  • 70,367
  • 12
  • 127
  • 192
  • 3
    Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/178389/discussion-on-answer-by-dfri-does-any-language-have-a-unary-boolean-toggle-opera). – Samuel Liew Aug 20 '18 at 23:03
44

In C++ it is possible to commit the Cardinal Sin of redefining the meaning of operators. With this in mind, and a little bit of ADL, all we need to do in order to unleash mayhem on our user base is this:

#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;
}

expected output:

6
0
1
0
1
Ghost4Man
  • 1,040
  • 1
  • 12
  • 19
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • 10
    “the Cardinal Sin of redefining the meaning of operators” — I get that you were exaggerating but it’s really *not* a cardinal sin to reassign new meanings to existing operators in general. – Konrad Rudolph Aug 20 '18 at 10:05
  • 6
    @KonradRudolph What I mean by this of course that an operator should make logical sense with respect to its usual arithmetic or logical meaning. 'operator+` for 2 strings is logical, since concatenation is similar (in our mind's eye) to addition or accumulation. `operator<<` has come to mean 'streamed out' because of its original abuse in the STL. It will not naturally mean 'apply the transform function on the RHS', which is essentially what I have re-purposed it for here. – Richard Hodges Aug 20 '18 at 10:11
  • 7
    I don’t think that’s a good argument, sorry. First off, string concatenation has *completely* different semantics from addition (it isn’t even commutative!). Secondly, by your logic `<<` is a bit shift operator, not a “stream out” operator. The problem with your redefinition isn’t that it’s inconsistent with existing meanings of the operator, but rather that it adds no value over a simple function call. – Konrad Rudolph Aug 20 '18 at 11:05
  • @KonradRudolph I think we are in agreement that this solution adds no value. – Richard Hodges Aug 20 '18 at 11:29
  • The use of `<<` (and `>>`) for streaming originates from I/O redirection in most UNIX shells. Early on there were some attempts at using `>` and `<` to be even more like the shell, but (according to Bjarne) while this worked fine with correct code, it produced bad enough error messages for incorrect code that `<<` and `>>` were deemed preferable. – Jerry Coffin Aug 20 '18 at 14:25
  • 8
    `<<` seems like a bad overload. I'd do `!invert= x;` ;) – Yakk - Adam Nevraumont Aug 20 '18 at 16:04
  • 13
    @Yakk-AdamNevraumont LOL, now you've got me started: https://godbolt.org/z/KIkesp – Richard Hodges Aug 20 '18 at 17:17
  • 1
    @KonradRudolph + and * are frequently used for non-commutative operations in math, so it's not that unusual to do something like that in C++. That being said, yeah I don't see the value of using an operator here - especially a binary operator. – Cubic Aug 21 '18 at 09:48
  • 1
    @RichardHodges Ooh, using Markdown in C++? I like it! *invert* x for `x=!x;`, and **enable** x for `x=true;`, You should write a standards proposal about it! – Joker_vD Aug 21 '18 at 10:46
  • @Yakk-AdamNevraumont: I was thinking of defining a wrapper for `bool` that had a `++` operator. (Incrementing a 1-bit value toggles it.) But confusing if you still want to also allow implicit conversion to `int`. Maybe call it `java_bool` and don't allow implicit-int conversion? I know Java doesn't allow the other way (you have to do `if(x != 0)` instead of just `if(x)`, if it's not bool. Oh, supercat's answer already points out that `--bool_var` works in C99/C++, working with implicit conversion to/from `int` instead of fighting against it. – Peter Cordes Aug 21 '18 at 12:27
  • 2
    TBH this kind of syntax adds nothing but confusion over some globally defined function `template T& invert(T& t) { t = !t; return t; }` – Matteo Italia Aug 21 '18 at 12:27
  • @RichardHodges: You're over-complicating the asm output by writing a `main` which uses `cout`. Just return a `bool` from a function. https://godbolt.org/z/FStTis has your code compiling to just `mov $1, %eax` / `ret`. – Peter Cordes Aug 21 '18 at 12:57
37

As long as we include assembly language...

FORTH

INVERT for a bitwise complement.

0= for a logical (true/false) complement.

DrSheldon
  • 589
  • 1
  • 4
  • 7
  • 4
    Arguable, in every stack-oriented language an unary `not` is a "toggle" operator :-) – Bergi Aug 21 '18 at 16:28
  • 2
    Sure, it's a bit of a sideways answer as the OP is clearly thinking about C-like languages that have a traditional assignment statement. I think sideways answers like this have value, if only to show a part of the programming world that the reader might not have thought of. ("There are more programming languages in heaven and earth, Horatio, than are dreampt of in our philosophy.") – Wayne Conrad Aug 21 '18 at 17:51
31

Decrementing a C99 bool will have the desired effect, as will incrementing or decrementing the bit types supported in some tiny-microcontroller dialects (which from what I've observed treat bits as single-bit wide bitfields, so all even numbers get truncated to 0 and all odd numbers to 1). I wouldn't particularly recommend such usage, in part because I'm not a big fan of the bool type semantics [IMHO, the type should have specified that a bool to which any value other than 0 or 1 is stored may behave when read as though it holds an Unspecified (not necessarily consistent) integer value; if a program is trying to store an integer value that isn't known to be 0 or 1, it should use !! on it first].

supercat
  • 77,689
  • 9
  • 166
  • 211
31

Assembly language

NOT eax

See https://www.tutorialspoint.com/assembly_programming/assembly_logical_instructions.htm

Adrian
  • 1,558
  • 1
  • 13
  • 31
  • 2
    I don't think this is quite what op had in mind, assuming this is x86 assembly. e.g. https://en.wikibooks.org/wiki/X86_Assembly/Logic `; here edx would be 0xFFFFFFFE because a bitwise NOT 0x00000001 = 0xFFFFFFFE` – BurnsBA Aug 20 '18 at 19:31
  • 8
    You can use all bits instead: NOT 0x00000000 = 0xFFFFFFFF – Adrian Aug 20 '18 at 19:33
  • 5
    Well, yes, though I was trying to the draw the distinction between boolean and bitwise operators. As op says in the question, assume the language has a well-defined boolean type: "(so no C-style int a = TRUE)." – BurnsBA Aug 21 '18 at 12:22
  • 5
    @BurnsBA: indeed, assembly languages don't have a single set of well-defined truthy / falsy values. Over on code-golf, much has been discussed about which values you're allowed to return for boolean problems in various languages. [Since asm doesn't have an `if(x)` construct](https://codegolf.meta.stackexchange.com/questions/2190/interpretation-of-truthy-falsey#comment9441_2194), it's totally reasonable to allow 0 / -1 as false/true, like for SIMD compares (http://felixcloutier.com/x86/PCMPEQB:PCMPEQW:PCMPEQD.html). But you're right that this breaks if you use it on any other value. – Peter Cordes Aug 21 '18 at 12:53
  • 4
    It's hard to have a single Boolean representation given that PCMPEQW results in 0/-1, but SETcc results in 0/+1. – Eugene Styer Aug 21 '18 at 14:11
  • many architectures don't have a NOT instruction. For example MIPS has NOR instead. Some others use different names like COM(plement), BIC (bit complement)... – phuclv Aug 21 '18 at 16:11
28

I'm assuming you're not going to be choosing a language based solely upon this :-) In any case, you can do this in C++ with something like:

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

See the following complete program for example:

#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);
}

This outputs, as expected:

false
true
false
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 2
    Would you want to `return b = !b` as well? Someone reading `foo = makenot(x) || y` or just a simple `foo = makenot(bar)` might assume that `makenot` was a pure function, and assume there was no side-effect. Burying a side-effect inside a larger expression is probably bad style, and the only benefit of a non-void return type is enabling that. – Peter Cordes Aug 21 '18 at 12:32
  • 2
    [@MatteoItalia suggests](https://stackoverflow.com/questions/51927109/does-any-language-have-a-unary-boolean-toggle-operator#comment90846989_51928360) `template T& invert(T& t) { t = !t; return t; }`, which being templated will convert to/from `bool` if used on a non-`bool` object. IDK if that's good or bad. Presumably good. – Peter Cordes Aug 21 '18 at 12:34
22

PostScript, being a concatenative, stack-oriented language like Forth, has a unary toggle, not. The not operator toggles the value on top of the stack. For example,

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

See the PostScript Language Reference Manual (pdf), p. 458.

Wayne Conrad
  • 103,207
  • 26
  • 155
  • 191
21

Visual Basic.Net supports this via an extension method.

Define the extension method like so:

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

And then call it like this:

Dim someVariable As Boolean
someVariable = True
someVariable.Flip

So, your original example would look something like:

me.DataSource.TrackedObject.CurrentValue.BooleanFlag.Flip
Reginald Blue
  • 930
  • 11
  • 26
  • 2
    While this does function as the shorthand the author was seeking, of course, you must use two operators to implement `Flip()`: `=` and `Not`. It's interesting to learn that in the case of calling `SomeInstance.SomeBoolean.Flip` it works even if `SomeBoolean` is a property, whereas the equivalent C# code would not compile. – Lance U. Matthews Aug 21 '18 at 05:53
15

This question is indeed interesting from a purely theoretical standpoint. Setting aside whether or not a unary, mutating boolean toggle operator would be useful, or why many languages have opted to not provide one, I ventured on a quest to see whether or not it indeed exists.

TL;DR apparently no, but Swift lets you implement one. If you'd only like to see how it's done, you can scroll to the bottom of this answer.


After a (quick) search to features of various languages, I'd feel safe to say that no language has implemented this operator as a strict mutating in-place operation (do correct me if you find one). So the next thing would be to see if there are languages that let you build one. What this would require is two things:

  1. being able to implement (unary) operators with functions
  2. allowing said functions to have pass-by-reference arguments (so that they may mutate their arguments directly)

Many languages will immediately get ruled out for not supporting either or both of these requirements. Java for one does not allow operator overloading (or custom operators) and in addition, all primitive types are passed by value. Go has no support for operator overloading (except by hacks) whatsoever. Rust only allows operator overloading for custom types. You could almost achieve this in Scala, which let's you use very creatively named functions and also omit parentheses, but sadly there's no pass-by-reference. Fortran gets very close in that it allows for custom operators, but specifically forbids them from having inout parameters (which are allowed in normal functions and subroutines).


There is however at least one language that ticks all the necessary boxes: Swift. While some people have linked to the upcoming .toggle() member function, you can also write your own operator, which indeed supports inout arguments. Lo and behold:

prefix operator ^

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

var foo = true
print(foo)
// true

^foo

print(foo)
// false
Lauri Piispanen
  • 2,067
  • 12
  • 20
14

In Rust, you can create your own trait to extend the types that implement the Not trait:

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);
}

You can also use ^= true as suggested, and in the case of Rust, there is no possible issue to do this because false is not a "disguised" integer like in C or C++:

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

    let mut b = false;
    b ^= true;
    assert_eq!(b, true);
}
Boiethios
  • 38,438
  • 19
  • 134
  • 183
6

In Python

Python supports such functionality, if the variable has bool type (which is True or False) with the exclusive or (^=) operator:

a = False
a ^= True
print(a)  # --> True
a ^= True
print(a)  # --> False
Andriy Ivaneyko
  • 20,639
  • 6
  • 60
  • 82
3

In C#:

boolean.variable.down.here ^= true;

The boolean ^ operator is XOR, and XORing with true is the same as inverting.

rakensi
  • 1,437
  • 1
  • 15
  • 20