Jak sprawdzić, czy obiekt Ruby jest logiczny


Odpowiedzi:


136

Najprościej przychodzi mi do głowy:

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

6
klasa X; def!; koniec własny; x = X.new; !! x == x # => true
Alexey

5
Tak, to się nazywa pisanie kaczkowe i podstawową zasadą OOP. Myślę, że to funkcja.
Konstantin Haase

62
Krótkie niekoniecznie oznacza proste. Przez co mam na myśli, wtf to jest?
Grant Birchmeier

11
Zamienia foo na wartość logiczną, sprawdza, czy to to samo, co foo.
Konstantin Haase,

9
Zauważ, że podwójna negacja jest uważana za zły styl przez niektóre warcaby (jak RuboCop ).
sschuberth

104

Uważam, że jest to zwięzłe i samodokumentujące się:

[true, false].include? foo

Jeśli używasz Rails lub ActiveSupport, możesz nawet wykonać bezpośrednie zapytanie za pomocą in?

foo.in? [true, false]

Sprawdzanie wszystkich możliwych wartości nie jest czymś, co polecałbym w przypadku wartości zmiennoprzecinkowych, ale jest wykonalne, gdy są tylko dwie możliwe wartości!


1
zdecydowanie najlepsza odpowiedź, chociaż podobało mi się też, foo == true or foo == falseże ktoś umieścił komentarz.
Ryan Taylor,

3
Podoba mi się to, ponieważ jest mniej tajemnicze w zamiarze niż !!foo == foo.
stringsn88keys

Po prostu pytoniczny! Zdecydowanie najbardziej semantyczna odpowiedź tutaj.
JM Janzen

85

W BooleanRubim nie ma klasy, jedynym sposobem sprawdzenia jest zrobienie tego, co robisz (porównanie obiektu z truei falselub klasą obiektu z TrueClassi FalseClass). Nie mogę jednak wymyślić, dlaczego potrzebujesz tej funkcji, czy możesz to wyjaśnić? :)

Jeśli jednak naprawdę potrzebujesz tej funkcji, możesz zhakować ją w:

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

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

1
próbuje wykonać rzutowanie na podstawie bieżącej wartości.
Lance Pollard,

75
- Dlaczego miałbyś kiedykolwiek co to? (i pochodne) to tylko jedno z najbardziej irytujących pytań, jakie może zadać inżynier :)
vemv

11
+1, ponieważ mogę tego używać w rspec jak:expect(some_method?(data)).to be_a(Boolean)
Automatico

3
Innym przypadkiem, w którym trzeba sprawdzić typ, jest zaimplementowanie adaptera bazy danych i potrzeba zawijania ciągów z "quotes"liczbami i wartościami logicznymi, ale nie z liczbami i wartościami logicznymi
Daniel Garmoshka

23

Jak wspomniano powyżej, nie ma klasy boolowskiej tylko TrueClass i FalseClass, jednak możesz użyć dowolnego obiektu jako podmiotu if /orrow i wszystko jest prawdziwe z wyjątkiem instancji FalseClass i nil

Testy logiczne zwracają wystąpienie FalseClass lub TrueClass

(1 > 0).class #TrueClass

Następująca monkeypatch do Object powie Ci, czy coś jest instancją TrueClass czy FalseClass

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

Wykonanie niektórych testów z irb daje następujące wyniki

?> "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
Prostsze po prostu pisać self == true or self == false. To jedyne wystąpienia TrueClass i FalseClass.
Chuck,

@chuck, który zwraca te same wyniki, z wyjątkiem Time.now.boolean? która zwraca nil. Każdy pomysł, dlaczego?
Steve Weet

Definiowanie sprawdzania klasy na sobie w metodzie nie jest oop. Należy zdefiniować dwie wersje boolean, jedną dla TrueClass / FalseClass i jedną dla Object.
Konstantin Haase

4
Powodem jest to, że błąd w wersji Time#==Rubiego 1.8 powoduje, że porównanie z wartościami innymi niż Time zwraca zero, a nie fałsz.
Chuck

17

Jeśli twój kod można rozsądnie zapisać jako instrukcję, jest to całkiem przyzwoite:

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

6

Obiekt, który jest wartością logiczną, będzie miał klasę TrueClass lub FalseClass, więc poniższy wiersz powinien załatwić sprawę

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

Poniższe również dałoby wynik sprawdzenia typu boolowskiego prawda / fałsz

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

4

Więc wypróbuj tę (x == true) ^ (x == false)notatkę, potrzebujesz nawiasu, ale jest piękniejszy i bardziej zwarty.

Spełnia nawet sugestie, takie jak „cuak”, ale nie „cuak” ... class X; def !; self end end ; x = X.new; (x == true) ^ (x == false)

Uwaga : zobacz, że jest to tak podstawowe, że możesz go używać również w innych językach, co nie zapewnia „rzeczy jest logiczne”.

Uwaga 2 : Możesz również użyć tego, aby powiedzieć, że rzecz jest jedną z ??:"red", "green", "blue"jeśliadd more XORS... lub powiesz, że ta rzecz jest jedną z ??:4, 5, 8, 35.


Dlaczego XOR? Dlaczego nie OR?
Nakilon


0

Nie. Nie tak, jak masz swój kod. Nie ma klasy o nazwie Boolean. Teraz, mając wszystkie odpowiedzi, powinieneś być w stanie je utworzyć i używać. Wiesz, jak tworzyć zajęcia, prawda? Przyjechałem tutaj tylko dlatego, że sam zastanawiałem się nad tym pomysłem. Wiele osób może powiedzieć „Dlaczego? Musisz tylko wiedzieć, w jaki sposób Ruby używa wartości logicznych”. Dlatego otrzymałeś odpowiedzi, które zrobiłeś. Więc dziękuję za pytanie. Do przemyślenia. Dlaczego Ruby nie ma klasy logicznej?

NameError: uninitialized constant Boolean

Pamiętaj, że obiekty nie mają typów. To są klasy. Obiekty mają dane. Dlatego kiedy mówisz o typach danych, jest to trochę mylące.

Spróbuj także rand 2, ponieważ rand 1 wydaje się zawsze dawać 0. rand 2 da 1 lub 0 kliknięć kilka razy tutaj. https://repl.it/IOPx/7

Chociaż sam nie wiedziałbym, jak zrobić klasę boolowską. Eksperymentowałem z tym, ale ...

class Boolean < TrueClass
  self
end

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

Przynajmniej mamy teraz tę klasę, ale kto wie, jak uzyskać właściwe wartości?

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.