Operator Boolean && dan ||

252

Menurut definisi bahasa R , perbedaan antara &dan &&(sesuai |dan ||) adalah bahwa yang pertama adalah vektor sedangkan yang terakhir tidak.

Menurut teks bantuan , saya membaca perbedaan yang mirip dengan perbedaan antara "Dan" dan "Dan juga" (sesuai "Atau" dan "OrElse") ... Artinya: Itu tidak semua evaluasi jika mereka tidak harus (mis. A atau B atau C selalu benar jika A benar, jadi berhentilah mengevaluasi apakah A benar)

Bisakah seseorang menjelaskan di sini? Juga, apakah ada AndAlso dan OrElse di R?

SFun28
sumber
Lihat juga pertanyaan serupa di stackoverflow.com/q/6933598/210673 dan stackoverflow.com/q/7953833/210673 (sekarang ditutup sebagai duplikat).
Aaron meninggalkan Stack Overflow
3
Saya pikir && dan || diimplementasikan dengan buruk di R. Dalam bahasa lain mereka adalah operator kondisional AND dan ATAU, mereka melakukan operasi logis DAN atau ATAU boolean, tetapi hanya mengevaluasi operan keduanya jika perlu. Di R jangan lakukan hal berguna.
skan

Jawaban:

340

Yang lebih pendek adalah vektor, artinya mereka dapat mengembalikan vektor, seperti ini:

((-2:2) >= 0) & ((-2:2) <= 0)
# [1] FALSE FALSE  TRUE FALSE FALSE

Bentuk yang lebih panjang mengevaluasi dari kiri ke kanan hanya memeriksa elemen pertama dari setiap vektor, sehingga memberi di atas

((-2:2) >= 0) && ((-2:2) <= 0)
# [1] FALSE

Seperti yang dikatakan halaman bantuan, ini membuat formulir yang lebih panjang "sesuai untuk aliran kontrol pemrograman dan biasanya lebih disukai di dalam klausa if."

Jadi, Anda ingin menggunakan formulir panjang hanya jika Anda yakin vektornya panjang satu.

Anda harus benar - benar yakin vektor Anda hanya panjang 1, seperti dalam kasus di mana mereka adalah fungsi yang hanya mengembalikan panjang 1 boolean. Anda ingin menggunakan formulir pendek jika vektornya panjang mungkin> 1. Jadi jika Anda tidak benar-benar yakin, Anda harus memeriksa dulu, atau menggunakan formulir pendek dan kemudian menggunakan alldan anymenguranginya menjadi panjang untuk digunakan dalam laporan aliran kontrol, seperti if.

Fungsi alldan anysering digunakan pada hasil perbandingan vektor untuk melihat apakah semua atau salah perbandingan benar, masing-masing. Hasil dari fungsi-fungsi ini pasti panjang 1 sehingga mereka cocok untuk digunakan dalam klausa if, sedangkan hasil dari perbandingan vektor tidak. (Meskipun hasil tersebut akan sesuai untuk digunakan di ifelse.

Satu perbedaan terakhir: &&dan ||hanya mengevaluasi sebanyak mungkin istilah yang mereka perlukan (yang tampaknya merupakan yang dimaksud dengan hubungan arus pendek). Misalnya, inilah perbandingan menggunakan nilai yang tidak ditentukan a; jika tidak korsleting, seperti &dan |tidak, itu akan memberikan kesalahan.

a
# Error: object 'a' not found
TRUE || a
# [1] TRUE
FALSE && a
# [1] FALSE
TRUE | a
# Error: object 'a' not found
FALSE & a
# Error: object 'a' not found

Akhirnya, lihat bagian 8.2.17 dalam The R Inferno , berjudul "and and andand".

Aaron meninggalkan Stack Overflow
sumber
Saya membandingkan logika panjang 1. Dokumentasi tidak jelas tentang mengapa lebih disukai untuk aliran kontrol. Apakah itu karena ia menggunakan "korsleting" dari jawaban @ Theo dan karenanya memiliki kinerja yang lebih baik?
SFun28
nggak. Cukup gunakan formulir pendek '&' - jawaban hubungan pendek salah.
M. Tibbits
1
Tidak, karena hanya menjamin jawaban TRUE / FALSE tunggal. Formulir yang lebih pendek bisa menghasilkan c(TRUE, FALSE), dan ifpernyataan itu tidak akan jelas. Jika Anda yakin semuanya memiliki panjang 1, maka ya, keduanya akan melakukannya, dan Anda benar bahwa "korsleting" adalah alasan untuk memilih satu. Namun, kata peringatan, pastikan Anda 100% yakin panjangnya hanya satu. Anda bisa mendapatkan bug yang benar-benar konyol jika tidak.
Aaron meninggalkan Stack Overflow
9
@ SFun28: Ya, korsleting adalah alasan yang disukai untuk kontrol aliran. Selain kinerja yang lebih baik, Anda mungkin tidak ingin mengevaluasi semua argumen. Contoh kanonik diberikan ?is.Runtuk memeriksa apakah Anda menjalankan R atau S-Plus. if(exists("is.R") && is.function(is.R) && is.R()). Jika is.Rtidak ada, maka Anda tidak ingin mengevaluasi is.function(is.R)karena akan menimbulkan kesalahan. Demikian juga jika is.Rbukan fungsi, Anda tidak ingin menyebutnya seolah-olah itu fungsi.
Richie Cotton
2
Dalam versi saat ini dari neraka R, bagian yang relevan sekarang 8.2.17 "dan dan dandan"
Silverfish
34

Jawaban tentang "korsleting" berpotensi menyesatkan, tetapi memiliki beberapa kebenaran (lihat di bawah). Dalam bahasa R / S, &&dan ||hanya mengevaluasi elemen pertama dalam argumen pertama. Semua elemen lain dalam vektor atau daftar diabaikan terlepas dari nilai yang pertama. Mereka operator dirancang untuk bekerja dengan if (cond) {} else{}konstruksi dan untuk program pengendalian langsung daripada membangun vektor baru .. The &dan |operator yang dirancang untuk bekerja pada vektor, sehingga mereka akan diterapkan "secara paralel", sehingga untuk berbicara, sepanjang argumen terpanjang. Kedua vektor perlu dievaluasi sebelum perbandingan dibuat. Jika vektornya tidak sama panjang, maka daur ulang argumen yang lebih pendek dilakukan.

Ketika argumen ke &&atau ||dievaluasi, ada "hubungan arus pendek" di mana jika salah satu nilai berturut-turut dari kiri ke kanan adalah determinatif, maka evaluasi berhenti dan nilai akhir dikembalikan.

> if( print(1) ) {print(2)} else {print(3)}
[1] 1
[1] 2
> if(FALSE && print(1) ) {print(2)} else {print(3)} # `print(1)` not evaluated
[1] 3
> if(TRUE && print(1) ) {print(2)} else {print(3)}
[1] 1
[1] 2
> if(TRUE && !print(1) ) {print(2)} else {print(3)}
[1] 1
[1] 3
> if(FALSE && !print(1) ) {print(2)} else {print(3)}
[1] 3

Keuntungan dari hubungan arus pendek hanya akan muncul ketika argumen membutuhkan waktu lama untuk mengevaluasi. Itu biasanya akan terjadi ketika argumen adalah fungsi yang memproses objek yang lebih besar atau memiliki operasi matematika yang lebih kompleks.

IRTFM
sumber
"hubungan arus pendek" adalah istilah baru bagi saya, tetapi bagi saya tampaknya jawaban yang menggambarkannya sesuai dengan apa yang Anda katakan &&dan ||.
Aaron meninggalkan Stack Overflow
@ DWin - dalam hal operator lebih dari 1 logis, mereka setara kan? Saya mencoba memahami mengapa mereka lebih disukai dalam aliran kontrol seperti yang dinyatakan oleh dokumentasi. Juga, apakah R memiliki konstruksi "korsleting"?
SFun28
Mereka BUKAN setara dengan vektor dengan panjang> 1
M. Tibbits
2
Benar bahwa jika argumen untuk &&berfungsi dan yang pertama salah, maka yang kedua tidak akan dievaluasi. Itu tidak benar untuk salah satu &atau ifelseyang akan mengevaluasi kedua argumen.
IRTFM
Bukankah itu jawaban Theo tentang hubungan arus pendek juga?
Aaron meninggalkan Stack Overflow
25

&&dan ||apa yang disebut "hubungan arus pendek". Itu berarti bahwa mereka tidak akan mengevaluasi operan kedua jika operan pertama cukup untuk menentukan nilai ekspresi.

Misalnya jika operan pertama &&salah, maka tidak ada gunanya mengevaluasi operan kedua, karena operan tidak dapat mengubah nilai ekspresi ( false && truedan false && falsekeduanya salah). Hal yang sama berlaku ||ketika operan pertama benar.

Anda dapat membaca lebih lanjut tentang ini di sini: http://en.wikipedia.org/wiki/Short-circuit_evaluation Dari tabel di halaman itu Anda dapat melihat yang &&setara dengan AndAlsodi VB.NET, yang saya anggap Anda maksud.

Theo
sumber
3
Ini harus cukup bukti bahwa itu adalah hubungan arus pendek: f <- function() { print('hello'); TRUE }; FALSE && f(). Ubah &dan perhatikan bahwa fungsi tersebut dievaluasi. QED.
Theo
2
Theo, ya, Anda benar itu &&dan ||korsleting. Tapi itu benar-benar poin yang cukup kecil dalam perbandingan antara bentuk pendek dan bentuk panjang; jauh lebih penting untuk memahami apa yang dilakukan masing-masing ketika inputnya adalah vektor.
Aaron meninggalkan Stack Overflow
2
@ Mbtits Sebenarnya ini bukan jawaban yang lengkap, tetapi pernyataan tentang korsleting sudah benar . Coba F & {message("Boo!");T}dan F && {message("Boo!");T}.
mbq