Як перевірити, чи об’єкт Ruby булевий


122

Я не можу легко перевірити, чи об'єкт є булевим. Чи є щось подібне в Рубі?

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

Зараз я це роблю і хотів би скоротити:

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

Відповіді:


136

Найпростіший спосіб, про який я можу придумати:

# checking whether foo is a boolean
!!foo == foo

6
клас X; def !; самозакінчення; х = X.нові; !! x == x # => вірно
Олексій

5
Так, це називається типом качок та основним принципом ООП. Я думаю, що це особливість.
Костянтин Хааз

62
Короткий не обов'язково означає простий. Під чим я маю на увазі, wtf це?
Грант Бірхмайер

11
Перетворює foo в булевий, перевіряє, чи це те саме, що і foo.
Костянтин Хаазе

9
Зауважте, що деякі перевірки подвійне заперечення вважають поганим стилем (наприклад, RuboCop ).
sschuberth

104

Я вважаю це стислим і самодокументальним:

[true, false].include? foo

Якщо ви використовуєте Rails або ActiveSupport, ви навіть можете зробити прямий запит, використовуючи in?

foo.in? [true, false]

Перевірка всіх можливих значень - це не те, що я рекомендував би для плавців, але здійсненний, коли є лише два можливі значення!


1
найкраща відповідь на сьогоднішній день, хоча мені також сподобалось, foo == true or foo == falseщо хтось поставив коментар.
Райан Тейлор

3
Мені це подобається, тому що він менш виразний за своєю метою !!foo == foo.
stringsn88keys

Відвертий пітонік! Однозначно найсемантичніша відповідь на сьогоднішній день.
JM Janzen

85

Там немає Booleanкласу в Ruby, єдиний спосіб перевірити це , щоб робити те , що ви робите (порівнюючи об'єкт з trueіfalse чи клас об'єкта проти TrueClassі FalseClass). Не можете подумати, навіщо вам потрібна ця функціональність, можете пояснити? :)

Якщо вам справді потрібна ця функціональність, ви можете зламати її в:

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

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

1
намагаючись зробити набір даних на основі поточного значення.
Ленс Поллард

75
- Навіщо ти коли-небудь це робив? (та похідні) - це лише одне з найбільш дратівливих питань, яким інженер може поставити інше :)
vemv

11
+1, оскільки я можу використовувати це у rspec, наприклад:expect(some_method?(data)).to be_a(Boolean)
Automatico

3
Інший випадок, коли потрібно перевірити тип, це коли ви впроваджуєте адаптер бази даних та вам потрібні рядки для обгортання з "quotes"номерами та булевими номерами, але не,
Daniel Garmoshka

23

Як зазначено вище, немає булевого класу просто TrueClass і FalseClass, проте ви можете використовувати будь-який об'єкт як предмет if / if і все вірно, крім випадків FalseClass і nil

Булеві тести повертають екземпляр FalseClass або TrueClass

(1 > 0).class #TrueClass

Наступна маніпуляція маніфесту до Object підкаже, чи є щось екземпляром TrueClass чи FalseClass

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

Запуск деяких тестів з irb дає такі результати

?> "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

4
Простіше просто писати self == true or self == false. Це єдині екземпляри TrueClass та FalseClass.
Чак

@chuck, який повертає ті самі результати, за винятком Time.now.boolean? який повертає нуль. Будь-яка ідея чому?
Стів Веет

Визначення перевірки класу self на методі дещо не є oop. Ви повинні визначити дві версії boolean, одну для TrueClass / FalseClass і одну для Object.
Костянтин Хааз

4
Причина полягає в тому, що помилка у версії Time#==в Ruby 1.8 викликає порівняння з значеннями, що не мають часу, повернути нуль, а не помилково.
Чак

17

Якщо ваш код можна розумно записати як випадок, це досить пристойно:

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

6

Об'єкт, що є булевим, або матиме клас TrueClass або FalseClass, тому наступний однокласник повинен зробити трюк

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

Наступне також дасть вам справжній / хибний логічний результат перевірки типу

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

4

Тож спробуйте це (x == true) ^ (x == false) ноту, вам потрібні дужки, але це красивіше і компактніше.

Він навіть передає запропоновані на кшталт "cuak", але не "cuak" ... class X; def !; self end end ; x = X.new; (x == true) ^ (x == false)

Примітка . Дивіться, що це настільки базово, що ви можете використовувати його і на інших мовах, що не забезпечує "булева річ".

Примітка 2 : Також ви можете використовувати це, щоб сказати, що це одна з ??:"red", "green", "blue"якщо виadd more XORS... або сказати, що ця річ є однією з ??:4, 5, 8, 35.


Чому XOR? Чому б АБО?
Накілон


0

Ні. Не так, як у вас є ваш код. Не існує жодного класу з ім'ям Boolean. Тепер, маючи всі ваші відповіді, ви повинні мати можливість створити та використати їх. Ви знаєте, як створити класи, чи не так? Я приїхав сюди лише тому, що я просто сам цікавився цій ідеї. Багато людей можуть сказати "Чому? Ви просто повинні знати, як Рубі використовує булеві". Ось чому ви отримали відповіді, які ви зробили. Тож дякую за запитання. Їжа для роздумів. Чому у Рубі немає булевого класу?

NameError: uninitialized constant Boolean

Майте на увазі, що об’єкти не мають типів. Вони - заняття. Об’єкти мають дані. Тож тому, коли ви говорите типи даних, це трохи помилка.

Спробуйте також rand 2, оскільки, здається, що rand 1 завжди дає 0. rand 2 дасть кілька разів виконати 1 або 0 клацання. https://repl.it/IOPx/7

Хоча я б не знав, як самостійно займатися створенням булевого класу. Я експериментував з цим, але ...

class Boolean < TrueClass
  self
end

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

Принаймні, у нас зараз цей клас, але хто знає, як отримати правильні значення?

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.