Cómo verificar si un objeto Ruby es un booleano

122

Parece que no puedo verificar si un objeto es booleano fácilmente. ¿Hay algo así en Ruby?

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

En este momento estoy haciendo esto y me gustaría acortarlo:

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

Respuestas:

136

La forma más simple en que puedo pensar:

# checking whether foo is a boolean
!!foo == foo
Konstantin Haase
fuente
66
clase X; def! auto fin final; x = X.nuevo; !! x == x # => verdadero
Alexey
55
Sí, eso se llama tipificación de pato y un principio básico de OOP. Creo que es una característica.
Konstantin Haase
62
Corto no necesariamente significa simple. Con lo que quiero decir, ¿qué es eso?
Grant Birchmeier
11
Convierte a foo en un booleano, comprueba si es lo mismo que foo.
Konstantin Haase
9
Tenga en cuenta que algunos verificadores consideran que la doble negación es de mal estilo (como RuboCop ).
sschuberth
104

Encuentro que esto es conciso y autodocumentado:

[true, false].include? foo

Si usa Rails o ActiveSupport, incluso puede hacer una consulta directa usando in?

foo.in? [true, false]

Verificar todos los valores posibles no es algo que recomendaría para flotadores, ¡pero es factible cuando solo hay dos valores posibles!

mahemoff
fuente
1
mejor respuesta, aunque también me gustó foo == true or foo == falseque alguien haya hecho un comentario.
Ryan Taylor
3
Me gusta esto porque tiene una intención menos críptica que la !!foo == foo.
stringsn88keys
¡Francamente pitónico! Definitivamente la respuesta más semántica aquí con diferencia.
JM Janzen
85

No hay ninguna Booleanclase en Ruby, la única manera de comprobar es hacer lo que está haciendo (comparando el objeto contra truey falseni la clase del objeto contra TrueClassy FalseClass). Sin embargo, no puedo pensar por qué necesitarías esta funcionalidad, ¿puedes explicarlo? :)

Sin embargo, si realmente necesita esta funcionalidad, puede hackearla en:

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

true.is_a?(Boolean) #=> true
false.is_a?(Boolean) #=> true
horseyguy
fuente
1
tratando de hacer una conversión de texto basada en el valor actual.
Lance Pollard
75
'¿Por qué quieres alguna vez eso?' (y derivados) es solo una de las preguntas más molestas que un ingeniero puede hacer otra :)
vemv
11
+1 porque puedo usar esto en rspec como:expect(some_method?(data)).to be_a(Boolean)
Automatico
3
Otro caso cuando necesita verificar el tipo, es cuando implementa el adaptador de base de datos y necesita cadenas de "quotes"
ajuste
23

Como se indicó anteriormente, no hay una clase booleana solo TrueClass y FalseClass, sin embargo, puede usar cualquier objeto como sujeto de if / less y todo es verdadero, excepto instancias de FalseClass y nil

Las pruebas booleanas devuelven una instancia de FalseClass o TrueClass

(1 > 0).class #TrueClass

El siguiente monkeypatch to Object le dirá si algo es una instancia de TrueClass o FalseClass

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

Ejecutar algunas pruebas con irb da los siguientes resultados

?> "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
fuente
44
Más simple de escribir self == true or self == false. Esas son las únicas instancias de TrueClass y FalseClass.
Chuck
@chuck que devuelve los mismos resultados, excepto Time.now.boolean? que devuelve nulo ¿Alguna idea de por qué?
Steve Weet
Definir un chequeo de clase en uno mismo en el método no es algo opuesto. Debe definir dos versiones de boolean, una para TrueClass / FalseClass y otra para Object.
Konstantin Haase
44
La razón es que un error en la versión de Time#==Ruby 1.8 hace que una comparación con valores que no son de tiempo devuelva nil en lugar de falso.
Chuck
17

Si su código se puede escribir sensatamente como una declaración de caso, esto es bastante decente:

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

Un objeto que es un booleano tendrá una clase de TrueClass o FalseClass, por lo que el siguiente trazo debería hacer el truco

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

Lo siguiente también le daría un resultado de verificación de tipo booleano verdadero / falso

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

Pruebe esta (x == true) ^ (x == false)nota, necesita el paréntesis, pero es más hermoso y compacto.

Incluso pasa el sugerido como "cuak" pero no un "cuak" ... class X; def !; self end end ; x = X.new; (x == true) ^ (x == false)

Nota : vea que esto es tan básico que también puede usarlo en otros idiomas, que no proporciona una "cosa booleana".

Nota 2 : También puede usar esto para decir que la cosa es una de ??:"red", "green", "blue"si ustedadd more XORS... o decir que esta cosa es una de ??:4, 5, 8, 35.

tyoc213
fuente
¿Por qué XOR? ¿Por qué no OR?
Nakilon
2

Esta gema agrega una clase booleana a Ruby con métodos útiles.

https://github.com/RISCfuture/boolean

Utilizar:

require 'boolean'

Entonces tu

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

funcionará exactamente como esperabas.

Convincente
fuente
0

No. No como si tuvieras tu código. No hay ninguna clase llamada booleana. Ahora, con todas las respuestas que tiene, debería poder crear una y usarla. ¿Sabes cómo crear clases, no? Solo vine aquí porque me preguntaba esta idea. Mucha gente podría decir "¿Por qué? Tienes que saber cómo Ruby usa el booleano". Por eso obtuviste las respuestas que obtuviste. Así que gracias por la pregunta. Comida para el pensamiento. ¿Por qué Ruby no tiene una clase booleana?

NameError: uninitialized constant Boolean

Tenga en cuenta que los objetos no tienen tipos. Son clases Los objetos tienen datos. Por eso, cuando dice tipos de datos, es un nombre poco apropiado.

También intente rand 2 porque rand 1 parece siempre dar 0. rand 2 dará 1 o 0 clic en ejecutar algunas veces aquí. https://repl.it/IOPx/7

Aunque no sabría cómo hacer una clase booleana yo mismo. He experimentado con eso pero ...

class Boolean < TrueClass
  self
end

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

Al menos tenemos esa clase ahora, pero ¿quién sabe cómo obtener los valores correctos?

Douglas G. Allen
fuente