Cara memeriksa apakah objek Ruby adalah Boolean

122

Saya tidak bisa memeriksa apakah suatu objek adalah boolean dengan mudah. Apakah ada yang seperti ini di Ruby?

true.is_a?(Boolean)
false.is_a?(Boolean)

Sekarang saya sedang melakukan ini dan ingin mempersingkatnya:

some_var = rand(1) == 1 ? true : false
(some_var.is_a?(TrueClass) || some_var.is_a?(FalseClass))
Lance Pollard
sumber

Jawaban:

136

Cara paling sederhana yang dapat saya pikirkan:

# checking whether foo is a boolean
!!foo == foo
Konstantin Haase
sumber
6
kelas X; def!; ujung diri sendiri; x = X. baru; !! x == x # => benar
Alexey
5
Ya, itulah yang disebut bebek mengetik dan prinsip inti OOP. Saya pikir itu sebuah fitur.
Konstantin Haase
62
Pendek tidak selalu berarti sederhana. Maksud saya, apa itu?
Grant Birchmeier
11
Mengubah foo menjadi boolean, periksa apakah itu sama dengan foo.
Konstantin Haase
9
Perhatikan bahwa negasi ganda dianggap gaya buruk oleh beberapa checker (seperti RuboCop ).
sschuberth
104

Saya merasa ini ringkas dan mendokumentasikan diri sendiri:

[true, false].include? foo

Jika menggunakan Rails atau ActiveSupport, Anda bahkan dapat melakukan kueri langsung menggunakan in?

foo.in? [true, false]

Memeriksa semua nilai yang mungkin bukanlah sesuatu yang saya rekomendasikan untuk float, tetapi layak jika hanya ada dua nilai yang memungkinkan!

mahemoff
sumber
1
jawaban terbaik sejauh ini, meskipun saya juga menyukai foo == true or foo == falseseseorang yang memberikan komentar.
Ryan Taylor
3
Saya suka ini karena maksudnya kurang samar daripada !!foo == foo.
stringsn88keys
Benar-benar pythonic! Jelas merupakan jawaban paling semantik di sini sejauh ini.
JM Janzen
85

Tidak ada Booleankelas di Ruby, satu-satunya cara untuk memeriksanya adalah dengan melakukan apa yang Anda lakukan (membandingkan objek dengan truedan falseatau kelas objek terhadap TrueClassdanFalseClass ). Tidak dapat memikirkan mengapa Anda membutuhkan fungsi ini, dapatkah Anda menjelaskan? :)

Namun, jika Anda benar - benar membutuhkan fungsi ini, Anda dapat meretasnya di:

module Boolean; end
class TrueClass; include Boolean; end
class FalseClass; include Boolean; end

true.is_a?(Boolean) #=> true
false.is_a?(Boolean) #=> true
horseyguy
sumber
1
mencoba melakukan typecasting berdasarkan nilai saat ini.
Lance Pollard
75
'Kenapa kamu pernah apa itu?' (dan turunannya) hanyalah salah satu pertanyaan paling menjengkelkan yang dapat diajukan oleh seorang insinyur :)
vemv
11
+1 karena saya dapat menggunakan ini di rspec seperti:expect(some_method?(data)).to be_a(Boolean)
Automatico
3
Kasus lain ketika perlu memeriksa jenis, adalah ketika Anda menerapkan adaptor database dan perlu membungkus string dengan "quotes"tetapi bukan angka dan boolean
Daniel Garmoshka
23

Seperti yang dinyatakan di atas tidak ada kelas boolean hanya TrueClass dan FalseClass namun Anda dapat menggunakan objek apa pun sebagai subjek jika / kecuali dan semuanya benar kecuali instance FalseClass dan nil

Pengujian Boolean mengembalikan instance FalseClass atau TrueClass

(1 > 0).class #TrueClass

Monkeypatch to Object berikut akan memberi tahu Anda apakah sesuatu adalah instance TrueClass atau FalseClass

class Object
  def boolean?
    self.is_a?(TrueClass) || self.is_a?(FalseClass) 
  end
end

Menjalankan beberapa tes dengan irb memberikan hasil sebagai berikut

?> "String".boolean?
=> false
>> 1.boolean?
=> false
>> Time.now.boolean?
=> false
>> nil.boolean?
=> false
>> true.boolean?
=> true
>> false.boolean?
=> true
>> (1 ==1).boolean?
=> true
>> (1 ==2).boolean?
=> true
Steve Weet
sumber
4
Lebih sederhana hanya untuk menulis self == true or self == false. Itu adalah satu-satunya contoh TrueClass dan FalseClass.
Chuck
@chuck yang mengembalikan hasil yang sama kecuali untuk Time.now.boolean? yang mengembalikan nihil. Tahu kenapa?
Steve Weet
Mendefinisikan pemeriksaan kelas pada diri sendiri dalam metode ini agak tidak tepat. Anda harus menentukan dua versi boolean, satu untuk TrueClass / FalseClass dan satu lagi untuk Object.
Konstantin Haase
4
Alasannya adalah bahwa bug di versi Time#==Ruby 1.8 menyebabkan perbandingan nilai non-Time menghasilkan nil, bukan false.
Chuck
17

Jika kode Anda dapat dengan bijaksana ditulis sebagai pernyataan kasus, ini cukup baik:

case mybool
when TrueClass, FalseClass
  puts "It's a bool!"
else
  puts "It's something else!"
end
Henrik N
sumber
6

Objek yang berupa boolean akan memiliki kelas TrueClass atau FalseClass sehingga satu baris berikut harus melakukan triknya

mybool = true
mybool.class == TrueClass || mybool.class == FalseClass
=> true

Berikut ini juga akan memberi Anda hasil pemeriksaan tipe boolean benar / salah

mybool = true    
[TrueClass, FalseClass].include?(mybool.class)
=> true
pengguna1966234
sumber
4

Jadi cobalah (x == true) ^ (x == false)catatan ini, Anda memerlukan tanda kurung tetapi ini lebih indah dan ringkas.

Itu bahkan melewati saran seperti "cuak" tetapi bukan "cuak" ... class X; def !; self end end ; x = X.new; (x == true) ^ (x == false)

Catatan : Perhatikan bahwa ini sangat mendasar sehingga Anda dapat menggunakannya dalam bahasa lain juga, yang tidak memberikan "thing is boolean".

Catatan 2 : Anda juga dapat menggunakan ini untuk mengatakan sesuatu adalah salah satu dari ??:"red", "green", "blue"jika Andaadd more XORS... atau mengatakan hal ini adalah salah satu dari ??:4, 5, 8, 35.

tyoc213
sumber
Mengapa XOR? Mengapa tidak ATAU?
Nakilon
2

Permata ini menambahkan kelas Boolean ke Ruby dengan metode yang berguna.

https://github.com/RISCfuture/boolean

Menggunakan:

require 'boolean'

Kemudian Anda

true.is_a?(Boolean)
false.is_a?(Boolean)

akan bekerja persis seperti yang Anda harapkan.

Meyakinkan
sumber
0

Tidak. Tidak seperti Anda memiliki kode Anda. Tidak ada kelas yang bernama Boolean. Sekarang dengan semua jawaban yang Anda miliki, Anda harus dapat membuat dan menggunakannya. Anda tahu cara membuat kelas bukan? Saya datang ke sini hanya karena saya sendiri yang bertanya-tanya tentang ide ini. Banyak orang mungkin berkata "Kenapa? Kamu harus tahu bagaimana Ruby menggunakan Boolean". Itulah mengapa Anda mendapatkan jawaban yang Anda lakukan. Jadi terima kasih atas pertanyaannya. Bahan untuk dipikirkan. Mengapa Ruby tidak memiliki kelas Boolean?

NameError: uninitialized constant Boolean

Perlu diingat bahwa Objek tidak memiliki tipe. Mereka adalah kelas. Objek memiliki data. Jadi itulah mengapa ketika Anda mengatakan tipe data itu sedikit keliru.

Coba juga rand 2 karena rand 1 sepertinya selalu memberikan 0. rand 2 akan memberikan 1 atau 0 klik berjalan beberapa kali di sini. https://repl.it/IOPx/7

Meskipun saya tidak tahu bagaimana cara membuat kelas Boolean sendiri. Saya telah bereksperimen dengan itu tapi ...

class Boolean < TrueClass
  self
end

true.is_a?(Boolean) # => false
false.is_a?(Boolean) # => false

Setidaknya kita memiliki kelas itu sekarang tetapi siapa yang tahu bagaimana mendapatkan nilai yang benar?

Douglas G. Allen
sumber