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.