Apa !! maksudnya di ruby?

134

Hanya ingin tahu apa yang !!ada di Ruby.

Cameron
sumber

Jawaban:

161

Tidak tidak. Ini digunakan untuk mengonversi nilai menjadi boolean:

!!nil   #=> false
!!"abc" #=> true
!!false #=> false

Ini biasanya tidak perlu digunakan karena satu-satunya nilai palsu untuk Ruby adalah nildan false, jadi biasanya yang terbaik adalah membiarkan konvensi itu berlaku.

Anggap saja sebagai

!(!some_val)

Satu hal yang digunakannya secara sah adalah mencegah sebagian besar data dikembalikan. Misalnya Anda mungkin tidak ingin mengembalikan 3MB data gambar dalam has_image?metode Anda , atau Anda mungkin tidak ingin mengembalikan seluruh objek pengguna Anda dalam logged_in?metode ini. Menggunakan !!mengubah objek-objek ini menjadi true/ false.

Alex Wayne
sumber
8
Ini bukan praktik yang buruk untuk menggunakan ini. Double bang sering digunakan dalam predikat (metode yang diakhiri dengan?) Untuk mengembalikan nilai boolean secara eksplisit.
Swanand
6
Alex, Anda tidak perlu khawatir mengembalikan objek besar, karena Ruby akan mengembalikan referensi, bukan salinan objek.
DSimon
10
@ DSimon, terkadang Anda perlu mengkhawatirkan objek besar, seperti saat mencetak atau mencatat nilai selama debugging.
Wayne Conrad
Mengapa tidak kembali saja .nil?daripada menggunakan !!? Apakah ada bedanya?
ashes999
3
Ada perbedaan ketika nilai Anda adalah booelan. !!true #=> truedantrue.nil? #=> false
Alex Wayne
31

Ia kembali truejika objek di sebelah kanan tidak nildan tidak false, falsejika nilataufalse

def logged_in?   
  !!@current_user
end
RichH
sumber
1
Apakah jelas itu berasal dari Restful_Auth ?! : D
Cameron
14

!berarti negate boolean state, two !s is nothing special, selain double negation.

!true == false
# => true

Ini biasanya digunakan untuk memaksa metode mengembalikan boolean. Ini akan mendeteksi segala jenis kebenaran, seperti string, integer dan apa yang tidak, dan mengubahnya menjadi boolean.

!"wtf"
# => false

!!"wtf"
# => true

Kasus penggunaan yang lebih nyata:

def title
  "I return a string."
end

def title_exists?
  !!title
end

Ini berguna ketika Anda ingin memastikan bahwa boolean dikembalikan. IMHO itu agak sia-sia, meskipun, melihat bahwa keduanya if 'some string'dan if truemerupakan aliran yang sama persis, tetapi beberapa orang merasa berguna untuk mengembalikan boolean secara eksplisit.

Agustus Lilleaas
sumber
bagi saya sepertinya cara yang lebih cepat daripada menggunakan pernyataan if atau operator terner. Karena Anda tidak bisa begitu saja kembali title, sebaiknya lakukan hal yang paling mendekati ... Saya kira
Carson Myers
6

Perhatikan bahwa idiom ini juga ada di bahasa pemrograman lain. C tidak memiliki booltipe intrinsik , jadi semua boolean diketik sebagai intgantinya, dengan nilai kanonik 0atau 1. Ambil contoh ini (tanda kurung ditambahkan untuk kejelasan):

!(1234) == 0
!(0) == 1
!(!(1234)) == 1

Sintaks "not-not" mengonversi bilangan bulat bukan nol menjadi 1, nilai sebenarnya boolean kanonis.

Secara umum, saya merasa jauh lebih baik untuk membuat perbandingan yang masuk akal daripada menggunakan ungkapan yang tidak umum ini:

int x = 1234;
if (!!x); // wtf mate
if (x != 0); // obvious
Tom
sumber
Atau hanya jika (x). !! berguna saat Anda perlu mendapatkan 0/1. Anda mungkin atau mungkin tidak mempertimbangkan (x)? 1: 0 lebih jelas.
derobert
3

Ini berguna jika Anda perlu melakukan eksklusif atau . Menyalin dari jawaban Matt Van Horn dengan sedikit modifikasi:

1 ^ true
TypeError: can't convert true into Integer

!!1 ^ !!true
=> false

Saya menggunakannya untuk memastikan dua variabel keduanya nihil, atau keduanya bukan nihil.

raise "Inconsistency" if !!a ^ !!b
Andrew Grimm
sumber
3

Ini adalah "negatif ganda", tetapi praktiknya tidak disarankan. Jika Anda menggunakan rubocop , Anda akan melihatnya mengeluh pada kode tersebut dengan aStyle/DoubleNegation pelanggaran.

The pemikiran negara:

Karena ini samar dan biasanya berlebihan, ini harus dihindari [lalu parafrase:] Ubah !!somethingke!something.nil?

Micah Elliott
sumber
1
Tapi ... !!false # => falsesementara!false.nil? # => true
Doug
@Doug Jika Anda tahu Anda memiliki nilai boolean, itu mubazir (cukup gunakan nilainya). Jika tidak, Anda dapat menggunakan !(foo.nil? || foo == false)- lebih bertele-tele, ya, tetapi tidak terlalu samar.
David Moles
0

Memahami cara kerjanya dapat berguna jika Anda perlu mengubah, katakanlah, enumerasi menjadi boolean. Saya memiliki kode yang melakukan hal itu, menggunakan classy_enumpermata:

class LinkStatus < ClassyEnum::Base
  def !
    return true
  end
end

class LinkStatus::No < LinkStatus
end

class LinkStatus::Claimed < LinkStatus
  def !
    return false
  end
end

class LinkStatus::Confirmed < LinkStatus
  def !
    return false
  end
end

class LinkStatus::Denied < LinkStatus
end

Kemudian di kode layanan yang saya miliki, misalnya:

raise Application::Error unless !!object.link_status   # => raises exception for "No" and "Denied" states.

Secara efektif operator bangbang telah menjadi apa yang mungkin saya tulis sebagai metode yang disebut to_bool.

inopinatus
sumber
0

Jawaban lain telah membahas apa !! dilakukan dan apakah itu praktik yang baik atau tidak.

Namun, tidak ada jawaban yang memberikan "cara Ruby standar" untuk mengubah nilai menjadi boolean.

true & variable

TrueClass, kelas dari nilai Ruby true, mengimplementasikan metode &, yang didokumentasikan sebagai berikut:

Pengembalian falsejika objini nilatau false, truesebaliknya.

Mengapa menggunakan negasi ganda yang kotor ketika perpustakaan standar telah Anda liput?

Richard-Degenne
sumber