Das ist also eher eine theoretische Frage. C ++ und direkt darauf basierende Sprachen (in) (Java, C #, PHP) verfügen über Verknüpfungsoperatoren , mit denen das Ergebnis der meisten Binäroperatoren dem ersten Operanden zugewiesen werden kann, z
a += 3; // for a = a + 3
a *= 3; // for a = a * 3;
a <<= 3; // for a = a << 3;
Aber wenn ich einen booleschen Ausdruck umschalten möchte, schreibe ich immer so etwas
a = !a;
was nervt wenn a
ein langer ausdruck ist wie.
this.dataSource.trackedObject.currentValue.booleanFlag =
!this.dataSource.trackedObject.currentValue.booleanFlag;
(Ja, Demeters Gesetz, ich weiß).
Also ich frage mich, ist es eine Sprache mit einem unären boolean Toggle Operator , der mich abzukürzen erlauben würde , a = !a
ohne Wiederholung der Ausdruck für a
, zum Beispiel
!=a;
// or
a!!;
Nehmen wir an, dass unsere Sprache einen richtigen booleschen Typ hat (wie bool
in C ++) und dass a
dieser vom Typ ist (also kein C-Stil int a = TRUE
).
Wenn Sie eine dokumentierte Quelle finden, würde mich auch interessieren, ob beispielsweise die C ++ - Designer erwogen haben, einen solchen Operator hinzuzufügen, als er bool
zu einem integrierten Typ wurde, und wenn ja, warum sie sich dagegen entschieden haben.
(Anmerkung: Ich weiß , dass einige Leute der Meinung sind , dass Zuordnung nicht verwenden sollten
, =
und dass ++
und +=
sind nicht nützlich Betreiber aber Design - Fehler, lassen Sie uns einfach davon ausgehen , ich bin glücklich mit ihnen und konzentrieren sich auf , warum sie bools nicht verlängern würde).
quelle
void Flip(bool& Flag) { Flag=!Flag; }
Die verkürzt Ihren langen Ausdruck.this.dataSource.trackedObject.currentValue.booleanFlag ^= 1;
*= -1
aber, was ich aus irgendeinem Grund intuitiver finde als^= true
.Antworten:
Diese Frage ist in der Tat aus rein theoretischer Sicht interessant. Abgesehen davon, ob ein unärer, mutierender boolescher Umschaltoperator nützlich wäre oder nicht , oder warum sich viele Sprachen dafür entschieden haben, keinen bereitzustellen, wagte ich mich auf die Suche, ob er tatsächlich existiert oder nicht.
TL; DR anscheinend nein, aber mit Swift können Sie eine implementieren. Wenn Sie nur sehen möchten, wie es gemacht wird, können Sie zum Ende dieser Antwort scrollen.
Nach einer (schnellen) Suche nach Funktionen verschiedener Sprachen kann ich mit Sicherheit sagen, dass keine Sprache diesen Operator als streng mutierende In-Place-Operation implementiert hat (korrigieren Sie mich, wenn Sie eine finden). Als nächstes sollten Sie also prüfen, ob es Sprachen gibt, mit denen Sie eine erstellen können. Was dies erfordern würde, sind zwei Dinge:
Viele Sprachen werden sofort ausgeschlossen, wenn sie eine oder beide dieser Anforderungen nicht unterstützen. Java erlaubt keine Überladung von Operatoren (oder benutzerdefinierte Operatoren) und außerdem werden alle primitiven Typen als Wert übergeben. Go unterstützt keinerlei Überlastung des Bedieners (außer durch Hacks ). Rust erlaubt nur das Überladen von Bedienern für benutzerdefinierte Typen. Sie könnten dies in Scala fast erreichen , wodurch Sie sehr kreativ benannte Funktionen verwenden und auch Klammern weglassen können, aber leider gibt es keine Referenzübergabe. Fortran kommt dem sehr nahe, da es benutzerdefinierte Operatoren zulässt, ihnen jedoch ausdrücklich verbietet, Inout zu haben Parameter (die in normalen Funktionen und Unterprogrammen zulässig sind).
Es gibt jedoch mindestens eine Sprache, die alle erforderlichen Kästchen ankreuzt: Swift . Während einige Leute auf die bevorstehende .toggle () -Mitgliedsfunktion verlinkt haben , können Sie auch Ihren eigenen Operator schreiben, der tatsächlich inout- Argumente unterstützt . Siehe da:
quelle
Das Boolesche Bit umschalten
Dieser Ansatz ist nicht wirklich ein reiner "mutierender Flip" -Operator, erfüllt jedoch die oben genannten Kriterien. Die rechte Seite des Ausdrucks enthält nicht die Variable selbst.
Jede Sprache mit einer booleschen XOR-Zuweisung (z. B.
^=
) würde das Umdrehen des aktuellen Werts einer Variablen ermöglichen, z. B.a
mittels XOR-Zuweisung antrue
:Wie von @cmaster in den Kommentaren unten ausgeführt, wird davon ausgegangen, dass
a
es sich um einen Typbool
handelt und nicht um eine Ganzzahl oder einen Zeiger. Wenna
es sich tatsächlich um etwas anderes handelt (z. B. um etwas, das nichtbool
auf einen "wahrheitsgemäßen" oder "falschen" Wert bewertet wird, mit einer Bitdarstellung, die nicht0b1
bzw.0b0
ist), gilt das Obige nicht.Für ein konkretes Beispiel ist Java eine Sprache, in der dies genau definiert ist und keine stillen Konvertierungen vorgenommen werden. Zitat von @ Boanns Kommentar von unten:
Schnell:
toggle()
Ab Swift 4.2 wurde der folgende Evolutionsvorschlag akzeptiert und umgesetzt:
Dies fügt
toggle()
demBool
Typ in Swift eine native Funktion hinzu .Dies ist per se kein Operator, ermöglicht jedoch einen sprachlichen Ansatz für das boolesche Umschalten.
quelle
In C ++ ist es möglich, die Hauptsünde der Neudefinition der Bedeutung von Operatoren zu begehen. In diesem Sinne und mit ein wenig ADL müssen wir nur Folgendes tun, um Chaos auf unserer Benutzerbasis auszulösen:
erwartete Ausgabe:
quelle
operator<<
ist aufgrund seines ursprünglichen Missbrauchs in der STL zu "gestreamt" geworden. Es wird natürlich nicht bedeuten, die Transformationsfunktion auf die RHS anzuwenden, was im Wesentlichen das ist, wofür ich sie hier neu bestimmt habe.<<
ein Bitverschiebungsoperator, kein "Stream-Out" -Operator. Das Problem bei Ihrer Neudefinition ist nicht, dass sie nicht mit den vorhandenen Bedeutungen des Operators übereinstimmt, sondern dass sie bei einem einfachen Funktionsaufruf keinen Wert hinzufügt.<<
scheint eine schlimme Überlastung zu sein. Ich würde tun!invert= x;
;)Solange wir Assemblersprache enthalten ...
FORTH
INVERT
für eine bitweise Ergänzung.0=
für eine logische (wahr / falsch) Ergänzung.quelle
not
Das Dekrementieren eines C99
bool
hat den gewünschten Effekt, ebenso wie das Inkrementieren oder Dekrementieren derbit
Typen, die in einigen Dialekten mit winzigen Mikrocontrollern unterstützt werden (die, wie ich beobachtet habe, Bits als ein Bit breite Bitfelder behandeln, sodass alle geraden Zahlen auf 0 und alle abgeschnitten werden ungerade Zahlen zu 1). Ich würde eine solche Verwendung nicht besonders empfehlen, zum Teil, weil ich kein großer Fan derbool
Typensemantik bin [IMHO sollte der Typ angegeben haben, dass sich einbool
Wert, für den ein anderer Wert als 0 oder 1 gespeichert ist, beim Lesen möglicherweise so verhält es enthält einen nicht spezifizierten (nicht unbedingt konsistenten) ganzzahligen Wert; Wenn ein Programm versucht, einen ganzzahligen Wert zu speichern, von dem nicht bekannt ist, dass er 0 oder 1 ist, sollte er!!
ihn zuerst verwenden.quelle
bool
bis C ++ 17 gemacht .Assemblersprache
Siehe https://www.tutorialspoint.com/assembly_programming/assembly_logical_instructions.htm
quelle
; here edx would be 0xFFFFFFFE because a bitwise NOT 0x00000001 = 0xFFFFFFFE
if(x)
Konstrukt hat , ist es völlig vernünftig, 0 / -1 als false / true zuzulassen, wie bei SIMD-Vergleichen ( felixcloutier.com/x86/PCMPEQB:PCMPEQW:PCMPEQD.html ). Aber Sie haben Recht, dass dies nicht funktioniert, wenn Sie es für einen anderen Wert verwenden.Ich gehe davon aus, dass Sie keine Sprache wählen werden, die nur darauf basiert :-) Auf jeden Fall können Sie dies in C ++ mit so etwas wie:
Siehe das folgende vollständige Programm zum Beispiel:
Dies gibt wie erwartet aus:
quelle
return b = !b
auch? Jemand, der liestfoo = makenot(x) || y
oder nur eine einfache,foo = makenot(bar)
könnte annehmen, dass diesmakenot
eine reine Funktion war, und annehmen, dass es keine Nebenwirkungen gab. Das Vergraben eines Nebeneffekts in einem größeren Ausdruck ist wahrscheinlich ein schlechter Stil, und der einzige Vorteil eines nicht leeren Rückgabetyps besteht darin, dies zu ermöglichen.template<typename T> T& invert(T& t) { t = !t; return t; }
, welche Vorlage in / von konvertiert wird,bool
wenn sie für ein Nicht-bool
Objekt verwendet wird. IDK, ob das gut oder schlecht ist. Vermutlich gut.PostScript ist eine verkettete , stapelorientierte Sprache wie Forth und hat einen unären Umschalter, nicht . Der Operator not schaltet den Wert oben auf dem Stapel um. Beispielsweise,
Weitere Informationen finden Sie im PostScript-Referenzhandbuch (pdf) . 458.
quelle
Visual Basic.Net unterstützt dies über eine Erweiterungsmethode.
Definieren Sie die Erweiterungsmethode folgendermaßen:
Und dann nenne es so:
Ihr ursprüngliches Beispiel würde also ungefähr so aussehen:
quelle
Flip()
:=
undNot
. Es ist interessant zu erfahren, dass es beim Aufrufen auchSomeInstance.SomeBoolean.Flip
dann funktioniert, wennSomeBoolean
es sich um eine Eigenschaft handelt, während der entsprechende C # -Code nicht kompiliert werden würde.In Rust können Sie Ihr eigenes Merkmal erstellen, um die Typen zu erweitern, die das
Not
Merkmal implementieren :Sie können auch
^= true
wie vorgeschlagen verwenden, und im Fall von Rust gibt es kein mögliches Problem, da diesfalse
keine "getarnte" Ganzzahl wie in C oder C ++ ist:quelle
In Python
Python unterstützt solche Funktionen, wenn die Variable mit dem Operator den Bool-Typ (True oder False) hat
exclusive or (^=)
:quelle
In C # :
Der boolesche ^ -Operator ist XOR, und XORing mit true ist dasselbe wie Invertieren.
quelle