So überprüfen Sie, ob ein Ruby-Objekt ein Boolescher Wert ist

121

Ich kann nicht leicht überprüfen, ob ein Objekt ein Boolescher Wert ist. Gibt es so etwas in Ruby?

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

Im Moment mache ich das und möchte es verkürzen:

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

Antworten:

136

Der einfachste Weg, den ich mir vorstellen kann:

# checking whether foo is a boolean
!!foo == foo
Konstantin Haase
quelle
6
Klasse X; def !; Selbstende Ende; x = X.neu; !! x == x # => true
Alexey
5
Ja, das nennt man Ententyping und ein Kernprinzip von OOP. Ich denke, es ist eine Funktion.
Konstantin Haase
62
Kurz bedeutet nicht unbedingt einfach. Womit meine ich, wtf ist das?
Grant Birchmeier
11
Verwandelt foo in einen Booleschen Wert und prüft, ob dies mit foo identisch ist.
Konstantin Haase
9
Beachten Sie, dass die doppelte Negation von einigen Prüfern (wie RuboCop ) als schlechter Stil angesehen wird .
sschuberth
103

Ich finde das prägnant und selbstdokumentierend:

[true, false].include? foo

Wenn Sie Rails oder ActiveSupport verwenden, können Sie sogar eine direkte Abfrage mit durchführen in?

foo.in? [true, false]

Das Überprüfen aller möglichen Werte würde ich für Floats nicht empfehlen, aber machbar, wenn es nur zwei mögliche Werte gibt!

Mahemoff
quelle
1
Die mit Abstand beste Antwort, obwohl mir auch gefallen hat, foo == true or foo == falsedass jemand einen Kommentar abgegeben hat.
Ryan Taylor
3
Ich mag das, weil es weniger kryptisch ist als das !!foo == foo.
Stringsn88keys
Gerade pythonisch! Auf jeden Fall die mit Abstand semantischste Antwort hier.
JM Janzen
85

BooleanIn Ruby gibt es keine Klasse. Die einzige Möglichkeit, dies zu überprüfen, besteht darin, das zu tun, was Sie tun (das Objekt mit trueund falseoder die Klasse des Objekts mit TrueClassund zu vergleichen FalseClass). Sie können sich nicht vorstellen, warum Sie diese Funktionalität benötigen würden, können Sie das erklären? :) :)

Wenn Sie diese Funktionalität jedoch wirklich benötigen, können Sie sie hacken:

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

true.is_a?(Boolean) #=> true
false.is_a?(Boolean) #=> true
horseyguy
quelle
1
versuchen, Typecasting basierend auf dem aktuellen Wert durchzuführen.
Lance Pollard
75
"Warum würdest du jemals was das?" (und Derivate) ist nur eine der nervigsten Fragen, die ein Ingenieur einem anderen stellen kann :)
vemv
11
+1, weil ich dies in rspec wie expect(some_method?(data)).to be_a(Boolean)
Automatico
3
Ein anderer Fall, in dem der Typ überprüft werden muss, ist, wenn Sie einen Datenbankadapter implementieren und Wrap-Strings mit, "quotes"aber nicht mit Zahlen und Booleschen
Werten
23

Wie oben erwähnt, gibt es keine boolesche Klasse, nur TrueClass und FalseClass. Sie können jedoch jedes Objekt als Subjekt von if / when verwenden und alles ist wahr, außer Instanzen von FalseClass und nil

Boolesche Tests geben eine Instanz der FalseClass oder TrueClass zurück

(1 > 0).class #TrueClass

Das folgende Monkeypatch to Object zeigt Ihnen, ob es sich bei einer Instanz um TrueClass oder FalseClass handelt

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

Das Ausführen einiger Tests mit irb führt zu den folgenden Ergebnissen

?> "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
quelle
4
Einfacher nur zu schreiben self == true or self == false. Dies sind die einzigen Instanzen von TrueClass und FalseClass.
Chuck
@chuck, das bis auf Time.now.boolean die gleichen Ergebnisse zurückgibt? was null zurückgibt. Irgendeine Idee warum?
Steve Weet
Das Definieren einer Klassenprüfung für sich selbst in der Methode ist etwas nicht oop. Sie sollten zwei Versionen von definieren boolean, eine für TrueClass / FalseClass und eine für Object.
Konstantin Haase
4
Der Grund dafür ist, dass ein Fehler in der Version von Time#==Ruby 1.8 dazu führt, dass ein Vergleich mit Nicht-Zeit-Werten eher null als falsch zurückgibt.
Chuck
17

Wenn Ihr Code sinnvoll als case-Anweisung geschrieben werden kann, ist dies ziemlich anständig:

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

Ein boolesches Objekt hat entweder die Klasse TrueClass oder FalseClass, daher sollte der folgende Einzeiler den Trick ausführen

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

Das Folgende würde Ihnen auch ein Ergebnis der booleschen Typprüfung für wahr / falsch geben

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

Probieren Sie diese (x == true) ^ (x == false)Notiz aus , Sie benötigen die Klammer, aber diese ist schöner und kompakter.

Es besteht sogar das vorgeschlagene wie "cuak", aber kein "cuak" ... class X; def !; self end end ; x = X.new; (x == true) ^ (x == false)

Hinweis : Stellen Sie sicher, dass dies so grundlegend ist, dass Sie es auch in anderen Sprachen verwenden können, ohne dass ein "Ding ist boolesch" angezeigt wird.

Anmerkung 2 : Sie können dies auch verwenden, um zu sagen, dass eines von ??: ist,"red", "green", "blue"wenn Sieadd more XORS... oder sagen, dass dieses Ding eines von ??: ist4, 5, 8, 35.

tyoc213
quelle
Warum XOR? Warum nicht ODER?
Nakilon
2

Dieses Juwel fügt Ruby eine Boolesche Klasse mit nützlichen Methoden hinzu.

https://github.com/RISCfuture/boolean

Verwenden:

require 'boolean'

Dann dein

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

wird genau so funktionieren, wie Sie es erwarten.

Überzeugbar
quelle
0

Nein, nicht so, als hättest du deinen Code. Es gibt keine Klasse namens Boolean. Mit all den Antworten, die Sie haben, sollten Sie in der Lage sein, eine zu erstellen und zu verwenden. Sie wissen, wie man Klassen erstellt, nicht wahr? Ich bin nur hergekommen, weil ich mich selbst über diese Idee gewundert habe. Viele Leute könnten sagen "Warum? Sie müssen nur wissen, wie Ruby Boolean verwendet". Deshalb hast du die Antworten bekommen, die du getan hast. Also danke für die Frage. Denkanstöße. Warum hat Ruby keine Boolesche Klasse?

NameError: uninitialized constant Boolean

Beachten Sie, dass Objekte keine Typen haben. Sie sind Klassen. Objekte haben Daten. Wenn Sie also Datentypen sagen, ist dies eine falsche Bezeichnung.

Versuchen Sie auch Rand 2, da Rand 1 immer 0 zu geben scheint. Rand 2 gibt hier einige Male 1 oder 0 Klicklauf. https://repl.it/IOPx/7

Obwohl ich nicht wissen würde, wie ich selbst eine Boolesche Klasse machen soll. Ich habe damit experimentiert, aber ...

class Boolean < TrueClass
  self
end

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

Zumindest haben wir diese Klasse jetzt, aber wer weiß, wie man die richtigen Werte erhält?

Douglas G. Allen
quelle