Does any language have a unary boolean toggle operator?
Clash Royale CLAN TAG#URR8PPP
up vote
103
down vote
favorite
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).
language-agnostic bitwise-operators negation
 |Â
show 16 more comments
up vote
103
down vote
favorite
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).
language-agnostic bitwise-operators negation
27
What about a functionvoid Flip(bool& Flag) Flag=!Flag;
The shortens your long expression.
â harper
Aug 20 at 8:50
61
this.dataSource.trackedObject.currentValue.booleanFlag ^= 1;
â Kamil Cuk
Aug 20 at 8:51
10
long expressions can be assigned to references to simplify the code
â Quentin 2
Aug 20 at 8:51
3
@KamilCuk This might work, but you mixup types. You assign an integer to an bool.
â harper
Aug 20 at 8:52
3
@user463035818 there is*= -1
though, which for some reason I find more intuitive than^= true
.
â CompuChip
Aug 20 at 9:07
 |Â
show 16 more comments
up vote
103
down vote
favorite
up vote
103
down vote
favorite
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).
language-agnostic bitwise-operators negation
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).
language-agnostic bitwise-operators negation
edited Aug 20 at 11:20
asked Aug 20 at 8:46
CompuChip
6,41431542
6,41431542
27
What about a functionvoid Flip(bool& Flag) Flag=!Flag;
The shortens your long expression.
â harper
Aug 20 at 8:50
61
this.dataSource.trackedObject.currentValue.booleanFlag ^= 1;
â Kamil Cuk
Aug 20 at 8:51
10
long expressions can be assigned to references to simplify the code
â Quentin 2
Aug 20 at 8:51
3
@KamilCuk This might work, but you mixup types. You assign an integer to an bool.
â harper
Aug 20 at 8:52
3
@user463035818 there is*= -1
though, which for some reason I find more intuitive than^= true
.
â CompuChip
Aug 20 at 9:07
 |Â
show 16 more comments
27
What about a functionvoid Flip(bool& Flag) Flag=!Flag;
The shortens your long expression.
â harper
Aug 20 at 8:50
61
this.dataSource.trackedObject.currentValue.booleanFlag ^= 1;
â Kamil Cuk
Aug 20 at 8:51
10
long expressions can be assigned to references to simplify the code
â Quentin 2
Aug 20 at 8:51
3
@KamilCuk This might work, but you mixup types. You assign an integer to an bool.
â harper
Aug 20 at 8:52
3
@user463035818 there is*= -1
though, which for some reason I find more intuitive than^= true
.
â CompuChip
Aug 20 at 9:07
27
27
What about a function
void Flip(bool& Flag) Flag=!Flag;
The shortens your long expression.â harper
Aug 20 at 8:50
What about a function
void Flip(bool& Flag) Flag=!Flag;
The shortens your long expression.â harper
Aug 20 at 8:50
61
61
this.dataSource.trackedObject.currentValue.booleanFlag ^= 1;
â Kamil Cuk
Aug 20 at 8:51
this.dataSource.trackedObject.currentValue.booleanFlag ^= 1;
â Kamil Cuk
Aug 20 at 8:51
10
10
long expressions can be assigned to references to simplify the code
â Quentin 2
Aug 20 at 8:51
long expressions can be assigned to references to simplify the code
â Quentin 2
Aug 20 at 8:51
3
3
@KamilCuk This might work, but you mixup types. You assign an integer to an bool.
â harper
Aug 20 at 8:52
@KamilCuk This might work, but you mixup types. You assign an integer to an bool.
â harper
Aug 20 at 8:52
3
3
@user463035818 there is
*= -1
though, which for some reason I find more intuitive than ^= true
.â CompuChip
Aug 20 at 9:07
@user463035818 there is
*= -1
though, which for some reason I find more intuitive than ^= true
.â CompuChip
Aug 20 at 9:07
 |Â
show 16 more comments
12 Answers
12
active
oldest
votes
up vote
117
down vote
Toggling the boolean bit
... that would allow me to abbreviate
a = !a
without repeating the
expression fora
...
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 ifa
is declared as an integer, but rather,
give a compile error. Soa ^= true;
is safe and well-defined in
Java.
Swift: toggle()
As of Swift 4.2, the following evolution proposal has been accepted and implemented:
- SE-0199: Adding toggle to Bool
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
tofalse
or
fromfalse
totrue
.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.
Comments are not for extended discussion; this conversation has been moved to chat.
â Samuel Liewâ¦
Aug 20 at 23:03
add a comment |Â
up vote
28
down vote
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
6
âÂÂ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 at 10:05
3
@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 at 10:11
3
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 at 11:05
6
<<
seems like a bad overload. I'd do!invert= x;
;)
â Yakk - Adam Nevraumont
Aug 20 at 16:04
10
@Yakk-AdamNevraumont LOL, now you've got me started: godbolt.org/z/KIkesp
â Richard Hodges
Aug 20 at 17:17
 |Â
show 7 more comments
up vote
25
down vote
As long as we include assembly language...
FORTH
INVERT
for a bitwise complement.
0=
for a logical (true/false) complement.
1
Arguable, in every stack-oriented language an unarynot
is a "toggle" operator :-)
â Bergi
Aug 21 at 16:28
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 at 17:51
add a comment |Â
up vote
21
down vote
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].
C++ did the same thing withbool
until C++17.
â Davis Herring
Aug 22 at 1:02
add a comment |Â
up vote
21
down vote
Assembly language
NOT eax
See https://www.tutorialspoint.com/assembly_programming/assembly_logical_instructions.htm
I don't think this is quite what op had in mind, assuming this is x86 assembly. e.g. en.wikibooks.org/wiki/X86_Assembly/Logic; here edx would be 0xFFFFFFFE because a bitwise NOT 0x00000001 = 0xFFFFFFFE
â BurnsBA
Aug 20 at 19:31
5
You can use all bits instead: NOT 0x00000000 = 0xFFFFFFFF
â 4dr14n31t0r Th3 G4m3r
Aug 20 at 19:33
2
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 at 12:22
2
@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 anif(x)
construct, it's totally reasonable to allow 0 / -1 as false/true, like for SIMD compares (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 at 12:53
1
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 at 14:11
 |Â
show 1 more comment
up vote
18
down vote
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
Would you want toreturn b = !b
as well? Someone readingfoo = makenot(x) || y
or just a simplefoo = makenot(bar)
might assume thatmakenot
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 at 12:32
@MatteoItalia suggeststemplate<typename T> T& invert(T& t) t = !t; return t;
, which being templated will convert to/frombool
if used on a non-bool
object. IDK if that's good or bad. Presumably good.
â Peter Cordes
Aug 21 at 12:34
add a comment |Â
up vote
15
down vote
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.
add a comment |Â
up vote
12
down vote
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
1
While this does function as the shorthand the author was seeking, of course, you must use two operators to implementFlip()
:=
andNot
. It's interesting to learn that in the case of callingSomeInstance.SomeBoolean.Flip
it works even ifSomeBoolean
is a property, whereas the equivalent C# code would not compile.
â BACON
Aug 21 at 5:53
add a comment |Â
up vote
7
down vote
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:
- being able to implement (unary) operators with functions
- 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
3
The language will provide this: github.com/apple/swift-evolution/blob/master/proposals/â¦
â Cristik
Aug 24 at 6:09
Yes, but the question specifically asked for an operator, not a member function.
â Lauri Piispanen
Aug 24 at 6:34
1
"Neither does Rust" => Yes it does
â Boiethios
2 days ago
@Boiethios thanks! Edited for Rust - only allows overloaded operators for custom types, though, so no dice.
â Lauri Piispanen
2 days ago
@LauriPiispanen The rule is more general than that, and due to orphan rule, FYI
â Boiethios
2 days ago
add a comment |Â
up vote
5
down vote
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);
add a comment |Â
up vote
-4
down vote
In Fortran you can use:
LOGICAL A = .TRUE.
A = .NOT. A
END
1
That isnâÂÂt a mutating operator.
â Davis Herring
Aug 22 at 1:00
2
A = .NOT. A
? I know nothing about Fortran, but how is that any different thana = !a;
in other languages? Which is exactly the expression the OP wanted to abbreviate...
â AJPerez
Aug 22 at 8:18
add a comment |Â
up vote
-4
down vote
In C#:
boolean.variable.down.here ^= true;
The boolean ^ operator is XOR, and XORing with true is the same as inverting.
add a comment |Â
12 Answers
12
active
oldest
votes
12 Answers
12
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
117
down vote
Toggling the boolean bit
... that would allow me to abbreviate
a = !a
without repeating the
expression fora
...
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 ifa
is declared as an integer, but rather,
give a compile error. Soa ^= true;
is safe and well-defined in
Java.
Swift: toggle()
As of Swift 4.2, the following evolution proposal has been accepted and implemented:
- SE-0199: Adding toggle to Bool
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
tofalse
or
fromfalse
totrue
.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.
Comments are not for extended discussion; this conversation has been moved to chat.
â Samuel Liewâ¦
Aug 20 at 23:03
add a comment |Â
up vote
117
down vote
Toggling the boolean bit
... that would allow me to abbreviate
a = !a
without repeating the
expression fora
...
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 ifa
is declared as an integer, but rather,
give a compile error. Soa ^= true;
is safe and well-defined in
Java.
Swift: toggle()
As of Swift 4.2, the following evolution proposal has been accepted and implemented:
- SE-0199: Adding toggle to Bool
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
tofalse
or
fromfalse
totrue
.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.
Comments are not for extended discussion; this conversation has been moved to chat.
â Samuel Liewâ¦
Aug 20 at 23:03
add a comment |Â
up vote
117
down vote
up vote
117
down vote
Toggling the boolean bit
... that would allow me to abbreviate
a = !a
without repeating the
expression fora
...
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 ifa
is declared as an integer, but rather,
give a compile error. Soa ^= true;
is safe and well-defined in
Java.
Swift: toggle()
As of Swift 4.2, the following evolution proposal has been accepted and implemented:
- SE-0199: Adding toggle to Bool
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
tofalse
or
fromfalse
totrue
.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.
Toggling the boolean bit
... that would allow me to abbreviate
a = !a
without repeating the
expression fora
...
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 ifa
is declared as an integer, but rather,
give a compile error. Soa ^= true;
is safe and well-defined in
Java.
Swift: toggle()
As of Swift 4.2, the following evolution proposal has been accepted and implemented:
- SE-0199: Adding toggle to Bool
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
tofalse
or
fromfalse
totrue
.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.
edited Aug 25 at 10:34
André Pena
26.4k28133181
26.4k28133181
answered Aug 20 at 8:52
dfri
33.1k44790
33.1k44790
Comments are not for extended discussion; this conversation has been moved to chat.
â Samuel Liewâ¦
Aug 20 at 23:03
add a comment |Â
Comments are not for extended discussion; this conversation has been moved to chat.
â Samuel Liewâ¦
Aug 20 at 23:03
Comments are not for extended discussion; this conversation has been moved to chat.
â Samuel Liewâ¦
Aug 20 at 23:03
Comments are not for extended discussion; this conversation has been moved to chat.
â Samuel Liewâ¦
Aug 20 at 23:03
add a comment |Â
up vote
28
down vote
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
6
âÂÂ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 at 10:05
3
@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 at 10:11
3
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 at 11:05
6
<<
seems like a bad overload. I'd do!invert= x;
;)
â Yakk - Adam Nevraumont
Aug 20 at 16:04
10
@Yakk-AdamNevraumont LOL, now you've got me started: godbolt.org/z/KIkesp
â Richard Hodges
Aug 20 at 17:17
 |Â
show 7 more comments
up vote
28
down vote
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
6
âÂÂ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 at 10:05
3
@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 at 10:11
3
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 at 11:05
6
<<
seems like a bad overload. I'd do!invert= x;
;)
â Yakk - Adam Nevraumont
Aug 20 at 16:04
10
@Yakk-AdamNevraumont LOL, now you've got me started: godbolt.org/z/KIkesp
â Richard Hodges
Aug 20 at 17:17
 |Â
show 7 more comments
up vote
28
down vote
up vote
28
down vote
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
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
answered Aug 20 at 10:03
Richard Hodges
53.4k55597
53.4k55597
6
âÂÂ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 at 10:05
3
@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 at 10:11
3
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 at 11:05
6
<<
seems like a bad overload. I'd do!invert= x;
;)
â Yakk - Adam Nevraumont
Aug 20 at 16:04
10
@Yakk-AdamNevraumont LOL, now you've got me started: godbolt.org/z/KIkesp
â Richard Hodges
Aug 20 at 17:17
 |Â
show 7 more comments
6
âÂÂ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 at 10:05
3
@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 at 10:11
3
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 at 11:05
6
<<
seems like a bad overload. I'd do!invert= x;
;)
â Yakk - Adam Nevraumont
Aug 20 at 16:04
10
@Yakk-AdamNevraumont LOL, now you've got me started: godbolt.org/z/KIkesp
â Richard Hodges
Aug 20 at 17:17
6
6
âÂÂ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 at 10:05
âÂÂ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 at 10:05
3
3
@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 at 10:11
@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 at 10:11
3
3
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 at 11:05
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 at 11:05
6
6
<<
seems like a bad overload. I'd do !invert= x;
;)â Yakk - Adam Nevraumont
Aug 20 at 16:04
<<
seems like a bad overload. I'd do !invert= x;
;)â Yakk - Adam Nevraumont
Aug 20 at 16:04
10
10
@Yakk-AdamNevraumont LOL, now you've got me started: godbolt.org/z/KIkesp
â Richard Hodges
Aug 20 at 17:17
@Yakk-AdamNevraumont LOL, now you've got me started: godbolt.org/z/KIkesp
â Richard Hodges
Aug 20 at 17:17
 |Â
show 7 more comments
up vote
25
down vote
As long as we include assembly language...
FORTH
INVERT
for a bitwise complement.
0=
for a logical (true/false) complement.
1
Arguable, in every stack-oriented language an unarynot
is a "toggle" operator :-)
â Bergi
Aug 21 at 16:28
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 at 17:51
add a comment |Â
up vote
25
down vote
As long as we include assembly language...
FORTH
INVERT
for a bitwise complement.
0=
for a logical (true/false) complement.
1
Arguable, in every stack-oriented language an unarynot
is a "toggle" operator :-)
â Bergi
Aug 21 at 16:28
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 at 17:51
add a comment |Â
up vote
25
down vote
up vote
25
down vote
As long as we include assembly language...
FORTH
INVERT
for a bitwise complement.
0=
for a logical (true/false) complement.
As long as we include assembly language...
FORTH
INVERT
for a bitwise complement.
0=
for a logical (true/false) complement.
answered Aug 20 at 22:47
Dr Sheldon
35115
35115
1
Arguable, in every stack-oriented language an unarynot
is a "toggle" operator :-)
â Bergi
Aug 21 at 16:28
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 at 17:51
add a comment |Â
1
Arguable, in every stack-oriented language an unarynot
is a "toggle" operator :-)
â Bergi
Aug 21 at 16:28
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 at 17:51
1
1
Arguable, in every stack-oriented language an unary
not
is a "toggle" operator :-)â Bergi
Aug 21 at 16:28
Arguable, in every stack-oriented language an unary
not
is a "toggle" operator :-)â Bergi
Aug 21 at 16:28
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 at 17:51
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 at 17:51
add a comment |Â
up vote
21
down vote
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].
C++ did the same thing withbool
until C++17.
â Davis Herring
Aug 22 at 1:02
add a comment |Â
up vote
21
down vote
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].
C++ did the same thing withbool
until C++17.
â Davis Herring
Aug 22 at 1:02
add a comment |Â
up vote
21
down vote
up vote
21
down vote
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].
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].
answered Aug 20 at 15:15
supercat
54.2k2111141
54.2k2111141
C++ did the same thing withbool
until C++17.
â Davis Herring
Aug 22 at 1:02
add a comment |Â
C++ did the same thing withbool
until C++17.
â Davis Herring
Aug 22 at 1:02
C++ did the same thing with
bool
until C++17.â Davis Herring
Aug 22 at 1:02
C++ did the same thing with
bool
until C++17.â Davis Herring
Aug 22 at 1:02
add a comment |Â
up vote
21
down vote
Assembly language
NOT eax
See https://www.tutorialspoint.com/assembly_programming/assembly_logical_instructions.htm
I don't think this is quite what op had in mind, assuming this is x86 assembly. e.g. en.wikibooks.org/wiki/X86_Assembly/Logic; here edx would be 0xFFFFFFFE because a bitwise NOT 0x00000001 = 0xFFFFFFFE
â BurnsBA
Aug 20 at 19:31
5
You can use all bits instead: NOT 0x00000000 = 0xFFFFFFFF
â 4dr14n31t0r Th3 G4m3r
Aug 20 at 19:33
2
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 at 12:22
2
@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 anif(x)
construct, it's totally reasonable to allow 0 / -1 as false/true, like for SIMD compares (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 at 12:53
1
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 at 14:11
 |Â
show 1 more comment
up vote
21
down vote
Assembly language
NOT eax
See https://www.tutorialspoint.com/assembly_programming/assembly_logical_instructions.htm
I don't think this is quite what op had in mind, assuming this is x86 assembly. e.g. en.wikibooks.org/wiki/X86_Assembly/Logic; here edx would be 0xFFFFFFFE because a bitwise NOT 0x00000001 = 0xFFFFFFFE
â BurnsBA
Aug 20 at 19:31
5
You can use all bits instead: NOT 0x00000000 = 0xFFFFFFFF
â 4dr14n31t0r Th3 G4m3r
Aug 20 at 19:33
2
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 at 12:22
2
@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 anif(x)
construct, it's totally reasonable to allow 0 / -1 as false/true, like for SIMD compares (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 at 12:53
1
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 at 14:11
 |Â
show 1 more comment
up vote
21
down vote
up vote
21
down vote
Assembly language
NOT eax
See https://www.tutorialspoint.com/assembly_programming/assembly_logical_instructions.htm
Assembly language
NOT eax
See https://www.tutorialspoint.com/assembly_programming/assembly_logical_instructions.htm
answered Aug 20 at 19:21
4dr14n31t0r Th3 G4m3r
39319
39319
I don't think this is quite what op had in mind, assuming this is x86 assembly. e.g. en.wikibooks.org/wiki/X86_Assembly/Logic; here edx would be 0xFFFFFFFE because a bitwise NOT 0x00000001 = 0xFFFFFFFE
â BurnsBA
Aug 20 at 19:31
5
You can use all bits instead: NOT 0x00000000 = 0xFFFFFFFF
â 4dr14n31t0r Th3 G4m3r
Aug 20 at 19:33
2
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 at 12:22
2
@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 anif(x)
construct, it's totally reasonable to allow 0 / -1 as false/true, like for SIMD compares (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 at 12:53
1
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 at 14:11
 |Â
show 1 more comment
I don't think this is quite what op had in mind, assuming this is x86 assembly. e.g. en.wikibooks.org/wiki/X86_Assembly/Logic; here edx would be 0xFFFFFFFE because a bitwise NOT 0x00000001 = 0xFFFFFFFE
â BurnsBA
Aug 20 at 19:31
5
You can use all bits instead: NOT 0x00000000 = 0xFFFFFFFF
â 4dr14n31t0r Th3 G4m3r
Aug 20 at 19:33
2
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 at 12:22
2
@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 anif(x)
construct, it's totally reasonable to allow 0 / -1 as false/true, like for SIMD compares (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 at 12:53
1
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 at 14:11
I don't think this is quite what op had in mind, assuming this is x86 assembly. e.g. en.wikibooks.org/wiki/X86_Assembly/Logic
; here edx would be 0xFFFFFFFE because a bitwise NOT 0x00000001 = 0xFFFFFFFE
â BurnsBA
Aug 20 at 19:31
I don't think this is quite what op had in mind, assuming this is x86 assembly. e.g. en.wikibooks.org/wiki/X86_Assembly/Logic
; here edx would be 0xFFFFFFFE because a bitwise NOT 0x00000001 = 0xFFFFFFFE
â BurnsBA
Aug 20 at 19:31
5
5
You can use all bits instead: NOT 0x00000000 = 0xFFFFFFFF
â 4dr14n31t0r Th3 G4m3r
Aug 20 at 19:33
You can use all bits instead: NOT 0x00000000 = 0xFFFFFFFF
â 4dr14n31t0r Th3 G4m3r
Aug 20 at 19:33
2
2
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 at 12:22
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 at 12:22
2
2
@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, it's totally reasonable to allow 0 / -1 as false/true, like for SIMD compares (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 at 12:53
@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, it's totally reasonable to allow 0 / -1 as false/true, like for SIMD compares (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 at 12:53
1
1
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 at 14:11
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 at 14:11
 |Â
show 1 more comment
up vote
18
down vote
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
Would you want toreturn b = !b
as well? Someone readingfoo = makenot(x) || y
or just a simplefoo = makenot(bar)
might assume thatmakenot
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 at 12:32
@MatteoItalia suggeststemplate<typename T> T& invert(T& t) t = !t; return t;
, which being templated will convert to/frombool
if used on a non-bool
object. IDK if that's good or bad. Presumably good.
â Peter Cordes
Aug 21 at 12:34
add a comment |Â
up vote
18
down vote
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
Would you want toreturn b = !b
as well? Someone readingfoo = makenot(x) || y
or just a simplefoo = makenot(bar)
might assume thatmakenot
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 at 12:32
@MatteoItalia suggeststemplate<typename T> T& invert(T& t) t = !t; return t;
, which being templated will convert to/frombool
if used on a non-bool
object. IDK if that's good or bad. Presumably good.
â Peter Cordes
Aug 21 at 12:34
add a comment |Â
up vote
18
down vote
up vote
18
down vote
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
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
edited Aug 20 at 9:12
answered Aug 20 at 8:50
paxdiablo
608k16412101639
608k16412101639
Would you want toreturn b = !b
as well? Someone readingfoo = makenot(x) || y
or just a simplefoo = makenot(bar)
might assume thatmakenot
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 at 12:32
@MatteoItalia suggeststemplate<typename T> T& invert(T& t) t = !t; return t;
, which being templated will convert to/frombool
if used on a non-bool
object. IDK if that's good or bad. Presumably good.
â Peter Cordes
Aug 21 at 12:34
add a comment |Â
Would you want toreturn b = !b
as well? Someone readingfoo = makenot(x) || y
or just a simplefoo = makenot(bar)
might assume thatmakenot
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 at 12:32
@MatteoItalia suggeststemplate<typename T> T& invert(T& t) t = !t; return t;
, which being templated will convert to/frombool
if used on a non-bool
object. IDK if that's good or bad. Presumably good.
â Peter Cordes
Aug 21 at 12:34
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 at 12:32
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 at 12:32
@MatteoItalia suggests
template<typename T> 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 at 12:34
@MatteoItalia suggests
template<typename T> 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 at 12:34
add a comment |Â
up vote
15
down vote
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.
add a comment |Â
up vote
15
down vote
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.
add a comment |Â
up vote
15
down vote
up vote
15
down vote
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.
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.
edited Aug 21 at 20:54
answered Aug 21 at 13:25
Wayne Conrad
69.2k18126162
69.2k18126162
add a comment |Â
add a comment |Â
up vote
12
down vote
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
1
While this does function as the shorthand the author was seeking, of course, you must use two operators to implementFlip()
:=
andNot
. It's interesting to learn that in the case of callingSomeInstance.SomeBoolean.Flip
it works even ifSomeBoolean
is a property, whereas the equivalent C# code would not compile.
â BACON
Aug 21 at 5:53
add a comment |Â
up vote
12
down vote
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
1
While this does function as the shorthand the author was seeking, of course, you must use two operators to implementFlip()
:=
andNot
. It's interesting to learn that in the case of callingSomeInstance.SomeBoolean.Flip
it works even ifSomeBoolean
is a property, whereas the equivalent C# code would not compile.
â BACON
Aug 21 at 5:53
add a comment |Â
up vote
12
down vote
up vote
12
down vote
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
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
answered Aug 20 at 17:22
Reginald Blue
341310
341310
1
While this does function as the shorthand the author was seeking, of course, you must use two operators to implementFlip()
:=
andNot
. It's interesting to learn that in the case of callingSomeInstance.SomeBoolean.Flip
it works even ifSomeBoolean
is a property, whereas the equivalent C# code would not compile.
â BACON
Aug 21 at 5:53
add a comment |Â
1
While this does function as the shorthand the author was seeking, of course, you must use two operators to implementFlip()
:=
andNot
. It's interesting to learn that in the case of callingSomeInstance.SomeBoolean.Flip
it works even ifSomeBoolean
is a property, whereas the equivalent C# code would not compile.
â BACON
Aug 21 at 5:53
1
1
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.â BACON
Aug 21 at 5:53
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.â BACON
Aug 21 at 5:53
add a comment |Â
up vote
7
down vote
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:
- being able to implement (unary) operators with functions
- 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
3
The language will provide this: github.com/apple/swift-evolution/blob/master/proposals/â¦
â Cristik
Aug 24 at 6:09
Yes, but the question specifically asked for an operator, not a member function.
â Lauri Piispanen
Aug 24 at 6:34
1
"Neither does Rust" => Yes it does
â Boiethios
2 days ago
@Boiethios thanks! Edited for Rust - only allows overloaded operators for custom types, though, so no dice.
â Lauri Piispanen
2 days ago
@LauriPiispanen The rule is more general than that, and due to orphan rule, FYI
â Boiethios
2 days ago
add a comment |Â
up vote
7
down vote
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:
- being able to implement (unary) operators with functions
- 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
3
The language will provide this: github.com/apple/swift-evolution/blob/master/proposals/â¦
â Cristik
Aug 24 at 6:09
Yes, but the question specifically asked for an operator, not a member function.
â Lauri Piispanen
Aug 24 at 6:34
1
"Neither does Rust" => Yes it does
â Boiethios
2 days ago
@Boiethios thanks! Edited for Rust - only allows overloaded operators for custom types, though, so no dice.
â Lauri Piispanen
2 days ago
@LauriPiispanen The rule is more general than that, and due to orphan rule, FYI
â Boiethios
2 days ago
add a comment |Â
up vote
7
down vote
up vote
7
down vote
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:
- being able to implement (unary) operators with functions
- 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
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:
- being able to implement (unary) operators with functions
- 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
edited 2 days ago
answered Aug 22 at 19:31
Lauri Piispanen
1,712916
1,712916
3
The language will provide this: github.com/apple/swift-evolution/blob/master/proposals/â¦
â Cristik
Aug 24 at 6:09
Yes, but the question specifically asked for an operator, not a member function.
â Lauri Piispanen
Aug 24 at 6:34
1
"Neither does Rust" => Yes it does
â Boiethios
2 days ago
@Boiethios thanks! Edited for Rust - only allows overloaded operators for custom types, though, so no dice.
â Lauri Piispanen
2 days ago
@LauriPiispanen The rule is more general than that, and due to orphan rule, FYI
â Boiethios
2 days ago
add a comment |Â
3
The language will provide this: github.com/apple/swift-evolution/blob/master/proposals/â¦
â Cristik
Aug 24 at 6:09
Yes, but the question specifically asked for an operator, not a member function.
â Lauri Piispanen
Aug 24 at 6:34
1
"Neither does Rust" => Yes it does
â Boiethios
2 days ago
@Boiethios thanks! Edited for Rust - only allows overloaded operators for custom types, though, so no dice.
â Lauri Piispanen
2 days ago
@LauriPiispanen The rule is more general than that, and due to orphan rule, FYI
â Boiethios
2 days ago
3
3
The language will provide this: github.com/apple/swift-evolution/blob/master/proposals/â¦
â Cristik
Aug 24 at 6:09
The language will provide this: github.com/apple/swift-evolution/blob/master/proposals/â¦
â Cristik
Aug 24 at 6:09
Yes, but the question specifically asked for an operator, not a member function.
â Lauri Piispanen
Aug 24 at 6:34
Yes, but the question specifically asked for an operator, not a member function.
â Lauri Piispanen
Aug 24 at 6:34
1
1
"Neither does Rust" => Yes it does
â Boiethios
2 days ago
"Neither does Rust" => Yes it does
â Boiethios
2 days ago
@Boiethios thanks! Edited for Rust - only allows overloaded operators for custom types, though, so no dice.
â Lauri Piispanen
2 days ago
@Boiethios thanks! Edited for Rust - only allows overloaded operators for custom types, though, so no dice.
â Lauri Piispanen
2 days ago
@LauriPiispanen The rule is more general than that, and due to orphan rule, FYI
â Boiethios
2 days ago
@LauriPiispanen The rule is more general than that, and due to orphan rule, FYI
â Boiethios
2 days ago
add a comment |Â
up vote
5
down vote
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);
add a comment |Â
up vote
5
down vote
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);
add a comment |Â
up vote
5
down vote
up vote
5
down vote
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);
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);
edited Aug 27 at 15:28
Shepmaster
133k10239363
133k10239363
answered Aug 27 at 12:48
Boiethios
8,42022762
8,42022762
add a comment |Â
add a comment |Â
up vote
-4
down vote
In Fortran you can use:
LOGICAL A = .TRUE.
A = .NOT. A
END
1
That isnâÂÂt a mutating operator.
â Davis Herring
Aug 22 at 1:00
2
A = .NOT. A
? I know nothing about Fortran, but how is that any different thana = !a;
in other languages? Which is exactly the expression the OP wanted to abbreviate...
â AJPerez
Aug 22 at 8:18
add a comment |Â
up vote
-4
down vote
In Fortran you can use:
LOGICAL A = .TRUE.
A = .NOT. A
END
1
That isnâÂÂt a mutating operator.
â Davis Herring
Aug 22 at 1:00
2
A = .NOT. A
? I know nothing about Fortran, but how is that any different thana = !a;
in other languages? Which is exactly the expression the OP wanted to abbreviate...
â AJPerez
Aug 22 at 8:18
add a comment |Â
up vote
-4
down vote
up vote
-4
down vote
In Fortran you can use:
LOGICAL A = .TRUE.
A = .NOT. A
END
In Fortran you can use:
LOGICAL A = .TRUE.
A = .NOT. A
END
edited Aug 22 at 0:38
Grant Miller
2,75761838
2,75761838
answered Aug 21 at 23:32
Fred Mitchell
1,5701022
1,5701022
1
That isnâÂÂt a mutating operator.
â Davis Herring
Aug 22 at 1:00
2
A = .NOT. A
? I know nothing about Fortran, but how is that any different thana = !a;
in other languages? Which is exactly the expression the OP wanted to abbreviate...
â AJPerez
Aug 22 at 8:18
add a comment |Â
1
That isnâÂÂt a mutating operator.
â Davis Herring
Aug 22 at 1:00
2
A = .NOT. A
? I know nothing about Fortran, but how is that any different thana = !a;
in other languages? Which is exactly the expression the OP wanted to abbreviate...
â AJPerez
Aug 22 at 8:18
1
1
That isnâÂÂt a mutating operator.
â Davis Herring
Aug 22 at 1:00
That isnâÂÂt a mutating operator.
â Davis Herring
Aug 22 at 1:00
2
2
A = .NOT. A
? I know nothing about Fortran, but how is that any different than a = !a;
in other languages? Which is exactly the expression the OP wanted to abbreviate...â AJPerez
Aug 22 at 8:18
A = .NOT. A
? I know nothing about Fortran, but how is that any different than a = !a;
in other languages? Which is exactly the expression the OP wanted to abbreviate...â AJPerez
Aug 22 at 8:18
add a comment |Â
up vote
-4
down vote
In C#:
boolean.variable.down.here ^= true;
The boolean ^ operator is XOR, and XORing with true is the same as inverting.
add a comment |Â
up vote
-4
down vote
In C#:
boolean.variable.down.here ^= true;
The boolean ^ operator is XOR, and XORing with true is the same as inverting.
add a comment |Â
up vote
-4
down vote
up vote
-4
down vote
In C#:
boolean.variable.down.here ^= true;
The boolean ^ operator is XOR, and XORing with true is the same as inverting.
In C#:
boolean.variable.down.here ^= true;
The boolean ^ operator is XOR, and XORing with true is the same as inverting.
answered Aug 24 at 6:42
rakensi
1,11811318
1,11811318
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51927109%2fdoes-any-language-have-a-unary-boolean-toggle-operator%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
27
What about a function
void Flip(bool& Flag) Flag=!Flag;
The shortens your long expression.â harper
Aug 20 at 8:50
61
this.dataSource.trackedObject.currentValue.booleanFlag ^= 1;
â Kamil Cuk
Aug 20 at 8:51
10
long expressions can be assigned to references to simplify the code
â Quentin 2
Aug 20 at 8:51
3
@KamilCuk This might work, but you mixup types. You assign an integer to an bool.
â harper
Aug 20 at 8:52
3
@user463035818 there is
*= -1
though, which for some reason I find more intuitive than^= true
.â CompuChip
Aug 20 at 9:07