Jadi ini lebih merupakan pertanyaan teoretis. C ++ dan bahasa (dalam) langsung berdasarkan itu (Java, C #, PHP) memiliki operator pintas untuk menetapkan hasil dari sebagian besar operator biner ke operan pertama, seperti
a += 3; // for a = a + 3
a *= 3; // for a = a * 3;
a <<= 3; // for a = a << 3;
tetapi ketika saya ingin beralih ekspresi boolean saya selalu menemukan diri saya menulis sesuatu seperti
a = !a;
yang menjadi menjengkelkan ketika a
ekspresi panjang seperti.
this.dataSource.trackedObject.currentValue.booleanFlag =
!this.dataSource.trackedObject.currentValue.booleanFlag;
(Ya, Hukum Demeter, saya tahu).
Jadi saya bertanya-tanya, apakah ada bahasa dengan operator toggle boolean unary yang akan memungkinkan saya untuk menyingkat a = !a
tanpa mengulangi ungkapan untuk a
, misalnya
!=a;
// or
a!!;
Mari kita asumsikan bahwa bahasa kita memiliki tipe boolean yang tepat (seperti bool
dalam C ++) dan itu a
adalah tipe itu (jadi tidak ada gaya-C int a = TRUE
).
Jika Anda dapat menemukan sumber yang terdokumentasi, saya juga akan tertarik untuk mengetahui apakah mis. Perancang C ++ telah mempertimbangkan untuk menambahkan operator seperti itu ketika bool
menjadi tipe bawaan dan jika demikian, mengapa mereka memutuskan untuk tidak melakukannya.
(Catatan: Saya tahu bahwa beberapa orang berpendapat bahwa penugasan tidak boleh digunakan
=
dan bahwa ++
dan +=
bukan operator yang berguna tetapi kelemahan desain; mari kita asumsikan saya senang dengan mereka dan fokus pada mengapa mereka tidak meluas ke bools).
sumber
void Flip(bool& Flag) { Flag=!Flag; }
, mempersingkat ekspresi panjang Anda.this.dataSource.trackedObject.currentValue.booleanFlag ^= 1;
*= -1
meskipun, yang karena alasan tertentu saya menemukan lebih intuitif daripada^= true
.Jawaban:
Pertanyaan ini memang menarik dari sudut pandang teori belaka. Mengesampingkan apakah operator beralih boolean unary, bermutasi akan berguna, atau mengapa banyak bahasa memilih untuk tidak menyediakan satu, saya memberanikan diri pada pencarian untuk melihat apakah itu benar-benar ada atau tidak.
TL; DR rupanya tidak, tetapi Swift memungkinkan Anda menerapkannya. Jika Anda hanya ingin melihat bagaimana ini dilakukan, Anda dapat menggulir ke bagian bawah jawaban ini.
Setelah pencarian (cepat) ke fitur dari berbagai bahasa, saya merasa aman untuk mengatakan bahwa tidak ada bahasa yang mengimplementasikan operator ini sebagai operasi in-place yang benar-benar bermutasi (perbaiki saya jika Anda menemukannya). Jadi, hal selanjutnya adalah melihat apakah ada bahasa yang memungkinkan Anda membangunnya. Apa yang dibutuhkan adalah dua hal:
Banyak bahasa akan segera dikesampingkan karena tidak mendukung salah satu atau kedua persyaratan ini. Java for one tidak memungkinkan overloading operator (atau operator kustom) dan di samping itu, semua tipe primitif diberikan nilai. Go tidak memiliki dukungan untuk overloading operator (kecuali dengan peretasan ) apa pun. Karat hanya memungkinkan overloading operator untuk jenis khusus. Anda hampir dapat mencapai ini di Scala , yang memungkinkan Anda menggunakan fungsi yang sangat kreatif dan juga menghilangkan tanda kurung, tetapi sayangnya tidak ada pass-by-reference. Fortran mendapat sangat dekat dalam yang memungkinkan untuk operator kustom, namun secara khusus melarang mereka dari memiliki inout parameter (yang diizinkan dalam fungsi dan subrutin normal).
Namun ada setidaknya satu bahasa yang menandai semua kotak yang diperlukan: Swift . Sementara beberapa orang telah menautkan ke fungsi anggota .toggle () yang akan datang , Anda juga dapat menulis operator Anda sendiri, yang memang mendukung argumen inout . Lihatlah:
sumber
Beralih sedikit boolean
Pendekatan ini sebenarnya bukan operator "mutating flip" yang murni, tetapi memenuhi kriteria Anda di atas; sisi kanan ekspresi tidak melibatkan variabel itu sendiri.
Bahasa apa pun dengan penugasan XOR boolean (mis.
^=
) Akan memungkinkan membalik nilai saat ini dari suatu variabel, katakanlaha
, dengan menggunakan penugasan XOR ketrue
:Seperti yang ditunjukkan oleh @cmaster dalam komentar di bawah ini, asumsi di atas
a
adalah tipebool
, dan bukan eg integer atau pointer. Jikaa
sebenarnya sesuatu yang lain (misalnya sesuatu yang tidakbool
mengevaluasi nilai "kebenaran" atau "palsu", dengan sedikit representasi yang tidak0b1
atau0b0
, masing-masing), hal di atas tidak berlaku.Sebagai contoh konkret, Java adalah bahasa di mana ini didefinisikan dengan baik dan tidak tunduk pada konversi diam. Mengutip komentar Boann dari bawah:
Cepat:
toggle()
Pada Swift 4.2, proposal evolusi berikut telah diterima dan diterapkan:
Ini menambahkan
toggle()
fungsi asli keBool
tipe di Swift.Ini bukan operator, per se, tetapi memungkinkan pendekatan bahasa asli untuk beralih boolean.
sumber
Dalam C ++ dimungkinkan untuk melakukan Dosa Kardinal mendefinisikan kembali makna operator. Dengan mengingat hal ini, dan sedikit ADL, yang perlu kita lakukan untuk melepaskan kekacauan pada basis pengguna kami adalah ini:
output yang diharapkan:
sumber
operator<<
telah berarti 'mengalir keluar' karena penyalahgunaan aslinya di STL. Ini tidak akan secara alami berarti 'menerapkan fungsi transformasi pada RHS', yang pada dasarnya adalah apa yang saya maksudkan di sini.<<
operator bit shift, bukan operator "stream out". Masalah dengan redefinisi Anda bukan karena tidak konsisten dengan makna operator yang ada, tetapi lebih karena tidak menambah nilai dibandingkan pemanggilan fungsi yang sederhana.<<
Sepertinya kelebihan yang buruk. Saya akan lakukan!invert= x;
;)Selama kami menyertakan bahasa rakitan ...
FORTH
INVERT
untuk komplemen bitwise.0=
untuk pelengkap yang logis (benar / salah).sumber
not
adalah operator "toggle" :-)Mengurangi C99
bool
akan memiliki efek yang diinginkan, karena akan menambah atau mengurangibit
jenis yang didukung dalam beberapa dialek mikrokontroler kecil (yang dari apa yang saya amati memperlakukan bit sebagai bitfield bit lebar tunggal, sehingga semua angka genap dipotong ke 0 dan semua angka ganjil ke 1). Saya tidak akan merekomendasikan penggunaan semacam itu, sebagian karena saya bukan penggemarbool
semantik tipe [IMHO, tipe tersebut seharusnya menentukan bahwabool
nilai yang selain 0 atau 1 disimpan mungkin berperilaku ketika dibaca seolah-olah ia memiliki nilai integer yang tidak ditentukan (tidak harus konsisten); jika suatu program mencoba untuk menyimpan nilai integer yang tidak dikenal sebagai 0 atau 1, itu harus digunakan!!
terlebih dahulu].sumber
bool
hingga C ++ 17 .bahasa campuran
Lihat https://www.tutorialspoint.com/assembly_programming/assembly_logical_instructions.htm
sumber
; here edx would be 0xFFFFFFFE because a bitwise NOT 0x00000001 = 0xFFFFFFFE
if(x)
konstruk , sangat masuk akal untuk mengizinkan 0 / -1 sebagai false / true, seperti untuk perbandingan SIMD ( felixcloutier.com/x86/PCMPEQB:PCMPEQW:PCMPEQD.html ). Tapi Anda benar bahwa ini rusak jika Anda menggunakannya pada nilai lain.Saya berasumsi Anda tidak akan memilih bahasa hanya berdasarkan ini :-) Bagaimanapun, Anda dapat melakukan ini di C ++ dengan sesuatu seperti:
Lihat program lengkap berikut ini misalnya:
Output ini, seperti yang diharapkan:
sumber
return b = !b
juga? Seseorang yang membacafoo = makenot(x) || y
atau sekadar sederhanafoo = makenot(bar)
mungkin menganggap itumakenot
adalah fungsi murni, dan menganggap tidak ada efek samping. Mengubur efek samping di dalam ekspresi yang lebih besar mungkin gaya yang buruk, dan satu-satunya manfaat dari tipe pengembalian non-void adalah memungkinkannya.template<typename T> T& invert(T& t) { t = !t; return t; }
, yang sedang templated akan dikonversi ke / daribool
jika digunakan pada non-bool
objek. IDK apakah itu baik atau buruk. Agaknya bagus.PostScript , menjadi bahasa konkatatif , berorientasi stack seperti Forth, memiliki toggle unary, bukan . The bukan Operator matikan nilai di atas tumpukan. Sebagai contoh,
Lihat Manual Referensi Bahasa PostScript (pdf) , hlm. 458.
sumber
Visual Basic.Net mendukung ini melalui metode ekstensi.
Tentukan metode ekstensi seperti ini:
Dan menyebutnya seperti ini:
Jadi, contoh asli Anda akan terlihat seperti:
sumber
Flip()
:=
danNot
. Sangat menarik untuk mengetahui bahwa dalam kasus memanggilSomeInstance.SomeBoolean.Flip
itu berfungsi bahkan jikaSomeBoolean
merupakan properti, sedangkan kode C # yang setara tidak akan dikompilasi.Di Rust, Anda bisa membuat sifat Anda sendiri untuk memperluas jenis yang menerapkan
Not
sifat itu:Anda juga dapat menggunakan
^= true
seperti yang disarankan, dan dalam kasus Rust, tidak ada masalah untuk melakukan hal ini karenafalse
bukan bilangan bulat "disamarkan" seperti di C atau C ++:sumber
Dengan Python
Python mendukung fungsi tersebut, jika variabel memiliki tipe bool (yang Benar atau Salah) dengan
exclusive or (^=)
operator:sumber
Dalam C # :
Operator boolean ^ adalah XOR, dan XORing dengan true sama dengan pembalik.
sumber