Como verificar se um objeto Ruby é um booleano

122

Não consigo verificar se um objeto é um booleano facilmente. Existe algo assim em Ruby?

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

No momento, estou fazendo isso e gostaria de reduzi-lo:

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

Respostas:

136

A maneira mais simples de pensar:

# checking whether foo is a boolean
!!foo == foo
Konstantin Haase
fonte
6
classe X; def!; auto fim final; x = X.novo; !! x == x # => true
Alexey
5
Sim, isso é chamado de digitação de pato e um princípio central do OOP. Eu acho que é uma característica.
Konstantin Haase
62
Curto não significa necessariamente simples. Com o que quero dizer, o que é isso?
Grant Birchmeier
11
Transforma foo em um booleano, verifica se é o mesmo que foo.
Konstantin Haase
9
Observe que a negação dupla é considerada um estilo ruim por alguns verificadores (como RuboCop ).
sschuberth
104

Acho isso conciso e auto-documentado:

[true, false].include? foo

Se estiver usando o Rails ou o ActiveSupport, você pode até fazer uma consulta direta usando in?

foo.in? [true, false]

Verificar todos os valores possíveis não é algo que eu recomendaria para carros alegóricos, mas é possível quando existem apenas dois valores possíveis!

mahemoff
fonte
1
melhor resposta de longe, embora eu também gostasse foo == true or foo == falseque alguém fizesse um comentário.
Ryan Taylor
3
Eu gosto disso porque é menos enigmático do que o !!foo == foo.
stringsn88keys
Absolutamente pitônico! Definitivamente, a resposta mais semântica aqui de longe.
JM Janzen
85

Não há Booleanclasse no Ruby, a única maneira de verificar é fazer o que você está fazendo (comparando o objeto contra truee / falseou a classe do objeto contra TrueClasse FalseClass). Mas não consegue pensar por que você precisaria dessa funcionalidade, pode explicar? :)

Se você realmente precisar dessa funcionalidade, poderá invadir:

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

true.is_a?(Boolean) #=> true
false.is_a?(Boolean) #=> true
horseyguy
fonte
1
tentando fazer a tipografia com base no valor atual.
usar o seguinte
75
"Por que você faria o quê?" (e derivados) é apenas uma das perguntas mais irritantes um engenheiro pode fazer outra :)
vemv
11
+1 porque eu posso usar isso no rspec como:expect(some_method?(data)).to be_a(Boolean)
Automatico
3
Outro caso quando necessidade de verificar o tipo, é quando você implementar adaptador de banco de dados e precisa envolver cordas com "quotes"mas não números e booleanos
Daniel Garmoshka
23

Como mencionado acima, não há classe booleana apenas TrueClass e FalseClass, no entanto, você pode usar qualquer objeto como assunto de if / a menos e tudo é verdadeiro, exceto instâncias de FalseClass e nulo

Testes booleanos retornam uma instância do FalseClass ou TrueClass

(1 > 0).class #TrueClass

O seguinte monkeypatch para Object informará se algo é uma instância de TrueClass ou FalseClass

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

A execução de alguns testes com o irb fornece os seguintes 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
fonte
4
Mais simples apenas para escrever self == true or self == false. Essas são as únicas instâncias de TrueClass e FalseClass.
Chuck
@ chuck que retorna os mesmos resultados, exceto Time.now.boolean? que retorna nulo. Alguma idéia do porquê?
23810 Steve Jobs
Definir um método de verificação de classe no self não é algo oop. Você deve definir duas versões boolean, uma para TrueClass / FalseClass e outra para Object.
Konstantin Haase
4
O motivo é que um bug na versão do Time#==Ruby 1.8 faz com que uma comparação com valores não-Time retorne nulo em vez de falso.
Chuck
17

Se seu código puder ser sensivelmente escrito como uma declaração de caso, isso é bastante decente:

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

Um objeto que é um booleano terá uma classe de TrueClass ou FalseClass, portanto, a seguinte linha única deve fazer o truque

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

O seguinte também forneceria resultado de verificação de tipo booleano verdadeiro / falso

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

Portanto, tente esta (x == true) ^ (x == false)nota que você precisa entre parênteses, mas isso é mais bonito e compacto.

Ele até passa o sugerido como "cuak", mas não um "cuak" ... class X; def !; self end end ; x = X.new; (x == true) ^ (x == false)

Nota : Veja que isso é tão básico que você pode usá-lo em outros idiomas também, que não fornece uma "coisa é booleana".

Nota 2 : Você também pode usar isso para dizer que uma das coisas é ??:"red", "green", "blue"se vocêadd more XORS... ou diz que essa é uma das coisas ??:4, 5, 8, 35.

tyoc213
fonte
Por que XOR? Por que não OU?
Nakilon 28/05/19
2

Essa gema adiciona uma classe booleana ao Ruby com métodos úteis.

https://github.com/RISCfuture/boolean

Usar:

require 'boolean'

Então seu

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

funcionará exatamente como você espera.

Convencível
fonte
0

Não. Não é como se você tivesse seu código. Não há nenhuma classe chamada booleana. Agora, com todas as respostas que você tem, você poderá criar uma e usá-la. Você sabe como criar aulas, não é? Só vim aqui porque estava me perguntando essa ideia. Muitas pessoas podem dizer "Por quê? Você só precisa saber como Ruby usa Boolean". É por isso que você obteve as respostas que obteve. Então, obrigado pela pergunta. Alimento para o pensamento. Por que Ruby não tem uma classe booleana?

NameError: uninitialized constant Boolean

Lembre-se de que os objetos não têm tipos. Eles são classes. Objetos possuem dados. É por isso que quando você diz que tipos de dados é um pouco impróprio.

Tente também o rand 2 porque o rand 1 parece sempre dar 0. rand 2 dará 1 ou 0 clique em executar algumas vezes aqui. https://repl.it/IOPx/7

Embora eu não saiba como fazer uma aula booleana. Eu experimentei com isso, mas ...

class Boolean < TrueClass
  self
end

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

Pelo menos temos essa classe agora, mas quem sabe como obter os valores certos?

Douglas G. Allen
fonte